IDOR (Insecure Direct Object Reference) es una vulnerabilidad de control de acceso en la que una aplicación web expone referencias internas a objetos (IDs de usuario, números de pedido, nombres de archivo) sin comprobar si el usuario autenticado tiene permiso para acceder a ese objeto en concreto.
Es el ejemplo más explotado de Broken Access Control, la vulnerabilidad número 1 del OWASP Top 10 desde 2021 y también en la edición 2025. Si todavía no conoces esa lista, échale un vistazo antes de seguir: te va a faltar contexto para entender lo que viene.
¿Qué es Broken Access Control y por qué IDOR es su caso estrella?
El control de acceso es el conjunto de reglas que decide qué puede hacer cada usuario dentro de una aplicación. Cuando esas reglas fallan, hablamos de Broken Access Control. Bajo ese paraguas caen muchos tipos de fallos: escalar privilegios de usuario normal a administrador, acceder a rutas de administración sin autenticarse… y, el más frecuente de todos, acceder a datos de otros usuarios cambiando un identificador en la petición.
Ese último caso es exactamente IDOR: el servidor confía en el ID que le llega del cliente sin comprobar si ese cliente es el propietario legítimo del recurso.
«Insecure Direct Object References occur when an application uses user-controllable input to access objects directly.»
— PortSwigger Web Security Academy, Insecure direct object references (IDOR)
La vulnerabilidad está catalogada como CWE-639 (Authorization Bypass Through User-Controlled Key) y aparece una y otra vez en los programas de bug bounty como uno de los hallazgos más reproducibles y con más impacto potencial.
Cómo funciona IDOR: el mecanismo básico
El escenario clásico: una aplicación devuelve información de un pedido en esta URL:
GET /api/orders?id=1042 HTTP/1.1
Host: tienda.ejemplo.com
Cookie: session=abc123xyz
El servidor responde con el pedido 1042 del usuario autenticado. Hasta aquí todo normal. El problema aparece cuando el atacante simplemente cambia el parámetro:
GET /api/orders?id=1043 HTTP/1.1
Host: tienda.ejemplo.com
Cookie: session=abc123xyz ← misma sesión, distinto ID
Si el servidor devuelve el pedido 1043, que pertenece a otro usuario, sin verificar que la sesión activa tiene derecho a verlo, hay un IDOR confirmado. El atacante puede iterar sobre todos los IDs posibles (enumeration) y descargar la información de miles de clientes.
El mismo patrón aplica a recursos en la ruta:
GET /facturas/factura_usuario_7891.pdf
↑
cambiar este número = acceso a facturas ajenas
O en el cuerpo de una petición POST:
POST /api/actualizar-perfil HTTP/1.1
Content-Type: application/json
{
"user_id": 9912, ← el atacante cambia su propio ID
"email": "atacante@evil.com"
}
Si el servidor no valida que user_id coincide con el usuario de la sesión, el atacante puede modificar el perfil de cualquier cuenta.
Tipos de IDOR: horizontal vs. vertical
| Tipo | Descripción | Ejemplo típico | Defensa clave |
|---|---|---|---|
| IDOR horizontal | Usuario A accede a datos de usuario B, ambos con el mismo nivel de privilegio | Cambiar ?user_id=123 a ?user_id=124 para ver el perfil de otro cliente |
Comprobar en el servidor que el recurso pertenece al usuario de la sesión |
| IDOR vertical | Usuario normal accede a recursos reservados a un rol superior (admin, moderador…) | Cambiar ?role=user a ?role=admin o acceder a /admin/users/42 |
Verificar el rol en el servidor, nunca confiar en parámetros del cliente |
| IDOR en referencia indirecta mal implementada | El ID se ofusca (UUID, hash), pero la lógica de autorización sigue sin comprobarse | UUID predecible o filtrado en otra respuesta; el servidor acepta cualquier UUID válido | La referencia indirecta ayuda, pero no reemplaza la comprobación de propiedad |
| IDOR en archivos estáticos | Documentos o imágenes con nombre predecible accesibles sin autenticación | /uploads/factura_2024_00432.pdf |
Servir archivos privados a través de un controlador autenticado, nunca de forma directa |
Ejemplo práctico en laboratorio: PortSwigger Web Security Academy
Aviso previo: practica siempre en entornos diseñados para ello. Intentar estas técnicas contra sistemas reales sin autorización expresa es ilegal en España (art. 197 bis del Código Penal) y en la mayoría de países. Los laboratorios de PortSwigger o OWASP Juice Shop existen precisamente para esto.
El laboratorio «IDOR vulnerability with direct reference to database objects» de PortSwigger Web Security Academy reproduce exactamente el escenario anterior. Estos son los pasos:
- Inicia sesión con la cuenta de prueba que da el lab (credenciales en la propia página).
- Navega a la sección «My account» → «Order history». Observa la URL o la petición en Burp Suite:
GET /download-transcript/2.txt HTTP/1.1 - Envía la petición a Burp Repeater y cambia el nombre del archivo:
GET /download-transcript/1.txt HTTP/1.1 - La respuesta contiene la transcripción de chat de otro usuario con su contraseña en texto claro. IDOR confirmado.
- Usa esa contraseña para acceder a la cuenta del administrador y completar el lab.
Este ejercicio demuestra cómo un ID secuencial en un recurso «estático» (fichero .txt) puede comprometer completamente una cuenta. Para más labs de hacking web con pasos guiados, consulta nuestro Curso de Hacking Web.
En OWASP Juice Shop también puedes practicar IDOR con el reto «View another user’s basket»: cambia el ID del carrito en la URL mientras tienes una sesión activa. El entorno es seguro, offline y perfectamente reproducible.
Cómo prevenir IDOR: las defensas reales
La seguridad por oscuridad (usar IDs largos, UUIDs o hashes) no es una defensa. Un UUID que se filtra en otra respuesta de la API, o que se puede enumerar indirectamente, sigue siendo explotable. Las únicas defensas reales actúan en la lógica del servidor.
1. Control de acceso del lado del servidor en cada petición
Nunca compruebes los permisos solo en el login o al cargar la página. Cada petición individual debe verificar, por separado, que el usuario autenticado tiene derecho a realizar esa acción sobre ese recurso concreto.
// Pseudocódigo — verificación correcta en cada petición
function getOrder(request, orderId) {
user = getAuthenticatedUser(request.session)
order = db.fetchOrder(orderId)
// ← Esta comprobación es la defensa clave
if (order.ownerId !== user.id) {
return HTTP 403 Forbidden
}
return order
}
2. Comprobar la propiedad del objeto, más allá de la autenticación
Autenticación (¿quién eres?) y autorización (¿qué puedes hacer?) son conceptos distintos. Un usuario puede estar perfectamente autenticado y, aun así, no tener derecho a ver ese pedido, ese archivo o ese perfil. Comprueba siempre los dos.
3. Referencias indirectas no predecibles (como capa adicional)
En lugar de exponer el ID de base de datos directamente, mapea los IDs a referencias indirectas por sesión o usa tokens opacos. Ejemplo: en vez de /order?id=1042, el servidor genera un token temporal /order?token=a3f9k2m que solo vale para esa sesión. Esto no sustituye la verificación de propiedad, pero pone más difícil las cosas al atacante.
4. No confíes en ningún dato que venga del cliente
IDs en parámetros GET, campos POST, cabeceras HTTP, cookies… cualquier valor que pueda manipular el usuario hay que tratarlo como no confiable. Si el valor no está firmado criptográficamente por el servidor (por ejemplo, dentro de un JWT con firma verificada), asume que puede haberse modificado.
5. Denegar por defecto (deny by default)
El mínimo privilegio aplicado al control de acceso: si no hay una regla explícita que permita el acceso, la respuesta debe ser 403 Forbidden. No al revés. Un sistema que deja pasar todo lo que no está expresamente bloqueado es una bomba de relojería.
6. Tests automatizados de autorización
Incluye en tu suite de pruebas casos específicos de IDOR: crea dos usuarios, autentica al usuario A y comprueba que no puede acceder a los recursos del usuario B. Herramientas como Burp Suite Professional (extensión Authorize) o scripts propios pueden automatizar esto a escala. Para aprender a usarlas en un programa de bug bounty, tenemos una guía completa.
Errores comunes: por qué «es que uso UUIDs» no basta
El error más extendido entre desarrolladores es creer que usar identificadores no predecibles resuelve el problema. No lo hace, por varias razones:
- Los UUIDs se filtran. Aparecen en logs, en respuestas de otras APIs, en URLs compartidas, en emails transaccionales… En cuanto el atacante tiene el UUID de un recurso ajeno, puede acceder a él si no hay verificación de propiedad.
- La enumeración no es el único vector. IDOR no requiere adivinar IDs secuenciales. Si la aplicación te da el UUID de otro usuario por otro camino (por ejemplo, en la lista de participantes de un evento), ya tienes el ID y puedes usarlo.
- Seguridad por oscuridad no es seguridad de verdad. Oscurecer no es controlar el acceso. Son capas distintas y se complementan, pero una no reemplaza a la otra.
Si quieres profundizar en los patrones de ataque y defensa de toda la familia de vulnerabilidades web, nuestra guía completa de hacking web cubre cada categoría del OWASP Top 10 con laboratorios prácticos.
Vídeo recomendado
Si prefieres aprender con vídeo, el canal oficial de PortSwigger en YouTube tiene una demostración práctica titulada «Testing for IDORs using Burp Suite» que muestra cómo identificar y confirmar un IDOR en un entorno de laboratorio:
Para una perspectiva orientada a bug bounty, el vídeo de NahamSec «Insecure Direct Object Reference / IDOR Explained // How to Bug Bounty» (youtube.com/watch?v=bCUqio4gNu4) explica cómo encontrar IDORs en programas reales.
📚 ¿Quieres practicarlo en un laboratorio legal, paso a paso? Lo trabajamos en el Módulo 8: Control de acceso roto e IDOR de nuestro Curso de Hacking Web.
Preguntas frecuentes
¿IDOR y Broken Access Control son lo mismo?
No exactamente. Broken Access Control es la categoría amplia (nº 1 del OWASP Top 10) que engloba todos los fallos de autorización: escalada de privilegios, acceso a rutas protegidas, manipulación de tokens… IDOR es el subtipo más común dentro de esa categoría: el que ocurre cuando se manipula una referencia directa a un objeto para acceder a datos de otro usuario.
¿Es ilegal practicar estas técnicas?
Sí, si lo haces en sistemas ajenos sin autorización expresa. En España, el artículo 197 bis del Código Penal tipifica el acceso no autorizado a sistemas informáticos con penas de hasta dos años de prisión. Practica siempre en laboratorios pensados para ello (PortSwigger, Juice Shop, HackTheBox, TryHackMe) o en programas de bug bounty con alcance definido.
¿Cómo sé si una aplicación que desarrollo es vulnerable a IDOR?
Busca cualquier punto de tu aplicación donde el cliente envíe un ID (en URL, en POST, en cabeceras) y el servidor devuelva o modifique datos asociados a ese ID. Para cada uno de esos puntos, pregúntate: «¿mi código verifica que el usuario autenticado es el propietario de este recurso, o solo verifica que está autenticado?» Si es lo segundo, tienes un IDOR.
¿Los escáneres automáticos detectan IDOR?
Con dificultad. A los escáneres tradicionales (DAST) les cuesta identificar IDOR porque para confirmar la vulnerabilidad necesitan dos cuentas diferentes y lógica de negocio contextual. Herramientas como Burp Suite Pro con la extensión Authorize automatizan parte del proceso, pero la revisión manual sigue siendo imprescindible. Es uno de los motivos por los que IDOR domina los top findings de bug bounty: los escáneres no lo pescan bien.
¿Qué diferencia hay entre IDOR en GET y en POST/PUT?
El vector cambia, pero el principio es el mismo. En GET el ID suele ir en la URL o en parámetros de query string, lo que lo hace más visible y fácil de manipular. En POST/PUT puede ir en el cuerpo JSON o en cabeceras, lo que lo hace menos obvio pero igualmente explotable. Ninguna de las dos variantes es «más segura» por usar un método HTTP distinto: la defensa siempre está en la verificación de propiedad en el servidor, no en el método.
Aviso legal y ético: Los conceptos y técnicas descritos en este artículo tienen únicamente finalidad educativa. Aplicar estas técnicas contra sistemas, aplicaciones o infraestructuras sin autorización expresa y por escrito del propietario es un delito tipificado en el artículo 197 bis del Código Penal español (acceso ilícito a sistemas informáticos), con penas de prisión de seis meses a dos años. Practica exclusivamente en entornos controlados y autorizados: laboratorios como PortSwigger Web Security Academy, OWASP Juice Shop, HackTheBox o TryHackMe, o dentro del alcance definido en programas de bug bounty.
