IDOR (Insecure Direct Object Reference)
Vulnerabilidad web crítica que permite a un atacante acceder directamente a objetos internos (archivos, registros de base de datos, identificadores de usuarios) sin verificación adecuada de autorización, simplemente manipulando parámetros en URLs o peticiones.
¿Qué es IDOR?
IDOR (Insecure Direct Object Reference, o Referencia Directa a Objetos Insegura) es una vulnerabilidad de control de acceso que ocurre cuando una aplicación web expone referencias directas a objetos internos del sistema sin validar adecuadamente si el usuario tiene permisos para acceder a ellos.
Ejemplo simple
## Usuario legítimo accede a su perfil
https://ejemplo.com/perfil?id=1234
## Atacante simplemente cambia el ID
https://ejemplo.com/perfil?id=5678
↑
ID de otro usuario
## Si no hay control de acceso... ¡bingo!
## El atacante ve datos del usuario 5678Cómo funciona un ataque IDOR
1. Identificación de referencias
El atacante busca parámetros que referencien objetos internos:
| Parámetro | Referencia |
|---|---|
?id=123 | ID de registro en base de datos |
?user=john | Nombre de usuario |
?file=documento.pdf | Nombre de archivo |
?invoice=2024-001 | Número de factura |
2. Manipulación sistemática
## Script simple para enumerar usuarios
for user_id in range(1, 10000):
url = f"https://ejemplo.com/api/user?id={user_id}"
response = requests.get(url)
if response.status_code == 200:
print(f"✓ Usuario {user_id}: {response.json()}")
# Guardar datos...3. Exfiltración masiva
Si el identificador es predecible —un DNI, un número de expediente correlativo—, la enumeración es mecánica:
## Enumeración secuencial de identificadores predecibles
12345678A → petición → registro completo
12345679B → petición → registro completo
12345680C → petición → registro completo
...La cifra de una filtración la anuncia siempre quien la vende
En cualquier incidente de este tipo, el número de registros que circula en los titulares procede del anuncio del atacante en un foro, no de una medición. Suele ser el máximo teórico —el tamaño de la población, el total de la tabla— y en las filtraciones que se han podido cotejar el volumen realmente verificable queda muy por debajo.
Para un peritaje la consecuencia es directa: el alcance no se copia del titular, se calcula de los logs. Peticiones distintas con respuesta 200, identificadores únicos alcanzados y ventana temporal — y lo que no se pueda contar así se declara como estimación, no como hecho.
¿Por qué es tan peligrosa?
1. Extremadamente simple de explotar
No requiere:
- ❌ Conocimientos avanzados de hacking
- ❌ Herramientas sofisticadas
- ❌ Vulnerabilidades complejas como SQLi o XSS
Solo requiere:
- ✅ Un navegador web (o script básico)
- ✅ Capacidad de modificar URLs
- ✅ Paciencia para enumerar
2. Difícil de detectar automáticamente
## Herramientas automáticas ven esto como "funcionando correctamente"
GET /user?id=123 → 200 OK ✓
GET /user?id=124 → 200 OK ✓
GET /user?id=125 → 200 OK ✓
## Pero no detectan que el usuario NO debería poder
## acceder a IDs 124 y 125Los escáneres de vulnerabilidades estándar no pueden identificar IDOR porque:
- Respuestas HTTP son “normales” (200 OK)
- No hay errores de base de datos
- No hay alertas en logs
- Funciona “como se diseñó” (mal)
3. Impacto devastador
| Datos comprometidos | Ejemplos reales |
|---|---|
| Información personal | DNI, direcciones, teléfonos |
| Datos bancarios | IBAN, cuentas, movimientos |
| Historial médico | Enfermedades, tratamientos |
| Documentos fiscales | Declaraciones, patrimonios |
| Archivos privados | Contratos, facturas, informes |
4. Clasificación OWASP Top 10
IDOR pertenece a Broken Access Control, que ocupa el primer puesto del OWASP Top 10:2025 —A01:2025— igual que lo ocupaba en la edición de 2021. Cuatro años en el mismo sitio dicen más que la posición en sí: es la categoría que no mejora, porque no se arregla con una biblioteca ni con un parche, sino revisando el control de acceso endpoint por endpoint.
Patrones típicos
Los tres que siguen no son expedientes: son las formas en que aparece esta vulnerabilidad, útiles para reconocerla.
1. El incidente que se anuncia y se desmiente
El patrón más frecuente en prensa no es una filtración confirmada, sino un anuncio en un foro seguido de un desmentido del titular de los datos. Ocurrió en febrero de 2026 con la Agencia Tributaria: se difundió una supuesta filtración masiva atribuida a un IDOR y la AEAT la descartó.
Para un perito el caso interesa precisamente por ahí — porque plantea la pregunta que hay que saber responder: ¿cómo se acredita que una filtración no ocurrió? No basta con negarla; hay que mostrar los logs de la ventana correspondiente, la ausencia del patrón de enumeración y, si el endpoint señalado existe, el control de acceso que devolvía 403. El análisis del episodio está en este artículo.
2. IDOR en plataformas educativas
Problema común: Profesores pueden ver notas de cualquier estudiante cambiando ?student_id=
## Profesor ve a su alumno
/grades?student_id=123&teacher_id=456
## Profesor cambia student_id
/grades?student_id=999&teacher_id=456
↑
Alumno de otro profesor
## Acceso concedido → IDOR3. IDOR en sistemas de salud
Caso hipotético: Paciente accede a su historial médico:
## Mi historial
https://hospital.com/historial?paciente=12345
## Cambio el número
https://hospital.com/historial?paciente=12346
↑
Historial de otra persona
## Si funciona → RGPD violation + IDORCómo detectar IDOR como perito forense
1. Análisis de logs del servidor
Busco patrones de enumeración secuencial:
## Ejemplo de análisis forense
cat access.log | \
grep "declaracion?id=" | \
awk '{print $1, $7}' | \
sort | uniq -c | sort -rn
## Resultado sospechoso:
## 1.284.117 peticiones desde 203.0.113.42
## IDs alcanzados: 12345678A, 12345679B, 12345680C…
## Ventana: 72 horas → ~5 peticiones/segundo sostenidas
## Indicio de enumeración automatizadaEl recuento del comando de arriba es de peticiones, no de registros expuestos, y son cosas distintas: una petición puede repetirse, fallar o devolver un registro vacío. El alcance real se cuenta sobre identificadores únicos que respondieron 200, y así es como debe escribirse en el informe.
Indicadores de ataque IDOR:
- ✅ Volumen anómalo de peticiones (millones en poco tiempo)
- ✅ Enumeración secuencial de identificadores
- ✅ Todas las respuestas HTTP 200 (sin rechazos)
- ✅ Misma IP o rango IP sospechoso
- ✅ Tiempo de respuesta constante (no hay validación)
2. Revisión de código fuente
## VULNERABLE ❌
@app.route('/declaracion')
def get_declaracion():
dni = request.args.get('dni')
# Consulta directa sin validación
data = db.query(
"SELECT * FROM declaraciones WHERE dni = ?",
dni
)
return jsonify(data) # Cualquiera puede ver cualquier DNI
## SEGURO ✅
@app.route('/declaracion')
@require_authentication
def get_declaracion():
dni = request.args.get('dni')
user_dni = get_authenticated_user_dni()
# Validación: solo puedes ver TU declaración
if dni != user_dni and not is_admin():
log_security_event(
"IDOR attempt",
user_dni,
dni,
request.remote_addr
)
return jsonify({"error": "Unauthorized"}), 403
data = db.query(
"SELECT * FROM declaraciones WHERE dni = ?",
dni
)
return jsonify(data)3. Análisis de tráfico de red
Con herramientas EDR/SIEM:
-- Detectar enumeración IDOR en SIEM
SELECT
source_ip,
COUNT(*) as requests,
MIN(timestamp) as first_seen,
MAX(timestamp) as last_seen
FROM http_logs
WHERE url LIKE '%?id=%'
GROUP BY source_ip
HAVING COUNT(*) > 1000
ORDER BY requests DESC;
-- Si una IP hace >1000 requests a endpoints con ?id=
-- → Investigar posible IDOR4. Forensic artifacts
Ante la sospecha de exfiltración, el orden importa más que las herramientas, y no es el intuitivo: se recoge primero lo que desaparece antes. Es el orden de volatilidad del RFC 3227, que el informe pericial debe poder justificar.
## 1. Lo volátil primero: memoria y estado de red del servidor EN CALIENTE
## (conexiones abiertas, procesos, sesiones) — se pierde al apagar
ss -tunap > estado_red.txt
ps auxww > procesos.txt
sha256sum estado_red.txt procesos.txt > evidencia.sha256
## 2. Logs, con su hash en el momento de la copia
tar czf logs_$(date +%F).tar.gz /var/log/apache2/*.log
sha256sum logs_*.tar.gz >> evidencia.sha256
## 3. Solo entonces, la imagen del disco
## En un servidor en marcha, dd sobre un sistema de ficheros montado
## produce una copia INCONSISTENTE: se hace sobre una instantánea del
## volumen, o con el sistema detenido, y así se declara en el informe
dd if=/dev/sda of=servidor.dd bs=4M status=progress
sha256sum servidor.dd >> evidencia.sha256Y una advertencia sobre el disco de un servidor ajeno
Cuando el servidor no es del cliente sino de un proveedor —un alojamiento compartido, una instancia gestionada—, la imagen completa contiene datos de terceros y adquirirla sin más excede casi siempre el objeto del encargo. En esos casos se acota a los registros del servicio afectado y se documenta expresamente qué quedó fuera y por qué, que es lo que sostiene la proporcionalidad de la actuación.
Cómo prevenir IDOR
1. Implementar control de acceso adecuado
## REGLA DE ORO: NUNCA confíes en IDs proporcionados por el usuario
def get_user_profile(user_id_from_url):
authenticated_user = get_current_user()
# Verificación OBLIGATORIA
if user_id_from_url != authenticated_user.id:
if not authenticated_user.has_role('admin'):
raise Unauthorized("Cannot access other user's profile")
return database.get_user(user_id_from_url)2. Usar referencias indirectas
En lugar de exponer IDs directos:
## MAL: ID directo en URL ❌
/invoice?id=12345
## BIEN: Token aleatorio no predecible ✅
/invoice?token=7f3a9c2e-5b1d-4e8f-9a3c-2d1f5e8a9c7b
## Mapeo interno:
## token → invoice_id + user_id
## Validar: invoice pertenece a user_id autenticado3. Validación en cada petición
## Middleware de validación
@app.before_request
def validate_access():
endpoint = request.endpoint
resource_id = request.args.get('id') or request.view_args.get('id')
if resource_id and not can_access(current_user, resource_id):
log_security_event(
event="access_denied",
user=current_user.id,
resource=resource_id,
ip=request.remote_addr
)
abort(403)4. Rate limiting
## Limitar requests por usuario
@limiter.limit("100 per minute")
@app.route('/api/user')
def get_user():
# Si excede límite → 429 Too Many Requests
pass
## Esto previene enumeración masiva5. Logging y alertas
## Detectar patrones sospechosos
if user_accessed_resources > 100 in last_hour:
alert_security_team(
"Possible IDOR enumeration",
user_id,
resources_accessed
)Desde la perspectiva legal
RGPD y IDOR
Una vulnerabilidad IDOR que exponga datos personales constituye:
Brecha de seguridad, y son dos artículos distintos, no uno:
- Art. 33 RGPD — notificación a la autoridad de control (la AEPD), en 72 horas desde que se tuvo constancia
- Art. 34 RGPD — comunicación al afectado, exigible cuando la brecha entrañe alto riesgo para sus derechos
- Art. 82 RGPD — derecho del afectado a ser indemnizado por los daños sufridos
Confundir el 33 con el 34 es el error más repetido al escribir sobre brechas, y cambia el destinatario de la obligación.
Medidas técnicas insuficientes (Art. 32 RGPD)
- Se encuadra en el art. 83.4.a, cuyo tope es 10 M€ o el 2 % del volumen de negocio anual global, el importe que sea mayor
- El control de acceso es medida técnica básica, así que difícilmente se defiende como riesgo asumido
Responsabilidad del responsable del tratamiento
- No es culpa del usuario que “descubrió” la vuln
- Es responsabilidad de quien no implementó controles
Como perito informático
En casos judiciales relacionados con IDOR, mi informe pericial documenta:
✅ Existencia de la vulnerabilidad ✅ Alcance del acceso no autorizado ✅ Análisis de logs (quién, cuándo, qué) ✅ Evaluación de medidas de seguridad ✅ Estimación de datos comprometidos ✅ Cadena de custodia de evidencias
Herramientas para testing de IDOR
Herramientas profesionales
| Herramienta | Uso |
|---|---|
| Burp Suite Pro | Interceptar y modificar peticiones |
| OWASP ZAP | Escáner automático de vulnerabilidades |
| Postman | Testing manual de APIs |
| Custom scripts | Enumeración automatizada (Python) |
Ejemplo de script de testing
import requests
def test_idor(base_url, my_id, test_ids):
"""
Prueba IDOR en un endpoint
"""
headers = {"Authorization": "Bearer MY_TOKEN"}
results = []
for test_id in test_ids:
url = f"{base_url}?id={test_id}"
response = requests.get(url, headers=headers)
if response.status_code == 200:
results.append({
"id": test_id,
"vulnerable": test_id != my_id,
"data": response.json()
})
return results
## Ejemplo de uso
vulnerable = test_idor(
"https://api.example.com/user",
my_id=1234,
test_ids=[1235, 1236, 1237, 1238] # IDs ajenos
)
if any(r['vulnerable'] for r in vulnerable):
print("⚠️ IDOR VULNERABILITY DETECTED")Checklist de seguridad para desarrolladores
Si eres desarrollador, verifica:
- Cada endpoint válida que el usuario autenticado tiene permiso para acceder al recurso solicitado
- No expones IDs secuenciales predecibles en URLs
- Usas referencias indirectas (UUIDs, tokens) cuando es posible
- Implementas rate limiting para prevenir enumeración
- Logs registran todos los accesos a recursos sensibles
- Alertas automáticas ante patrones de enumeración
- Tests de seguridad incluyen casos de IDOR
- Code review específico para control de acceso
Cuándo interviene un perito informático
No en el momento de arreglar la vulnerabilidad —eso lo hace quien desarrolla—, sino cuando hace falta acreditar qué ocurrió y con qué alcance: porque hay una reclamación, una brecha de datos que notificar, o una investigación de la AEPD.
Lo que sostiene ese trabajo es el rastro, y el rastro caduca: los logs del servidor rotan, se comprimen y se borran según la política de retención, que en muchas instalaciones no llega al mes. Preservarlos con su huella es lo primero y lo más urgente, antes incluso de saber si hubo o no exfiltración; después ya no hay nada que analizar. Y una vez preservados, la cadena de custodia es lo que permite que lo analizado siga valiendo meses más tarde.
El análisis lo firma un perito informático forense, que responde de él ante el tribunal.
Los logs de un IDOR se borran solos antes de que llegue la demanda
La retención habitual de un servidor web no llega al mes: cuando el procedimiento arranca, el rastro de la enumeración ya no está. Preservación de registros con SHA-256, cálculo del alcance real e informe pericial.
Referencias técnicas
- OWASP: Insecure Direct Object Reference Prevention
- OWASP Top 10:2025 — A01 Broken Access Control · edición anterior: A01:2021
- PortSwigger: IDOR Vulnerabilities
- CWE-639: Authorization Bypass Through User-Controlled Key
Nota del perito: IDOR es una de las vulnerabilidades más subestimadas pero más explotadas en aplicaciones web. Su simplicidad de explotación combinada con su dificultad de detección la convierte en un vector de ataque preferido por atacantes de todos los niveles.
Preguntas Frecuentes
¿Qué es una vulnerabilidad IDOR?
IDOR (Insecure Direct Object Reference) es una vulnerabilidad que permite acceder a objetos internos cambiando parámetros en URLs. Por ejemplo, cambiar ?id=123 por ?id=124 para ver datos de otro usuario si no hay control de acceso.
¿Por qué IDOR es tan peligrosa?
Porque es extremadamente simple de explotar (solo requiere un navegador), difícil de detectar automáticamente, y puede permitir acceso a millones de registros mediante enumeración secuencial.
¿Se puede detectar IDOR en análisis forense?
Sí. Como perito, analizo logs del servidor buscando patrones de enumeración secuencial, volumen anómalo de peticiones, y respuestas HTTP 200 donde deberían ser 403. También reviso el código fuente para validar controles de acceso.
¿Necesitas un peritaje forense?
Si necesitas ayuda profesional con análisis forense digital, estoy aquí para ayudarte.
Solicitar Consulta Gratuita
