Saltearse al contenido

IDOR & control de acceso

El control de acceso roto (Broken Access Control) es, año tras año, el nº1 del OWASP Top 10. Ocurre cuando la aplicación no verifica que el usuario tenga permiso para la acción o el recurso que solicita. El IDOR (Insecure Direct Object Reference) es su variante más conocida: un identificador manipulable (id, uuid, nombre de fichero, clave) y el servidor no comprueba que ese objeto pertenezca a quien lo pide.

GET /api/invoices/1001 -> tu factura
GET /api/invoices/1002 -> ¿la de otro usuario? (IDOR)

No necesita payloads: basta cambiar un valor. Por eso es trivial de explotar y, a la vez, de los fallos más frecuentes y de mayor impacto, sobre todo en APIs.

Lectura/modificación/borrado de datos de otros usuarios, acceso a funciones administrativas, toma de cuentas (un IDOR de escritura sobre el email ajeno suele ser ATO directo) y fuga masiva si el endpoint permite enumerar.

El error de raíz es confiar en el cliente: ocultar opciones en la UI, validar solo en el front, o asumir que “si conoce el ID, es suyo”. Hay dos comprobaciones distintas y ambas deben estar en el servidor, por cada petición:

  • Autenticación: ¿quién eres? (identidad de la sesión).
  • Autorización: ¿puedes hacer esta acción con este objeto? (rol + propiedad).
  • Horizontal: acceder a recursos de otro usuario del mismo nivel (IDOR clásico, en OWASP API = BOLA, Broken Object Level Authorization).
  • Vertical: alcanzar funciones de un rol superior (usuario normal → /admin; en OWASP API = BFLA, Broken Function Level Authorization).
  • A nivel de función: la UI oculta el botón, pero el endpoint sigue accesible; o el control se aplica solo en un paso del flujo.
  • Mass assignment: enviar campos extra (role=admin) que el binder acepta (ver ficha propia).
  • Dependiente de contexto/estado: autorizado en un estado del flujo, no en otro.
  • Método de las dos cuentas (A y B): haz una acción con A y repítela con la sesión de B cambiando el identificador al de A. Si B accede, hay IDOR. Repite al revés y entre roles (normal vs admin).
  • Busca identificadores en todos los sitios: URL/path, query, cuerpo/JSON, cabeceras, cookies, y dentro del JWT (claims como user_id).
  • Prueba tipos de ID: incrementales (enumerables), UUIDs filtrados en otras respuestas/logs/correos, nombres de fichero, IDs codificados (base64/hash) que siguen siendo adivinables.
  • Escalada vertical: accede a rutas/métodos de admin con usuario normal; prueba métodos HTTP alternativos (PUT, PATCH, DELETE), endpoints “ocultos”, versiones antiguas de API (/v1 vs /v2) y paneles debug.
  • Revisa flujos multi-paso: ¿se valida la autorización en todos los pasos o solo al principio?

A mano (automatizar el método de las dos cuentas)

Sección titulada «A mano (automatizar el método de las dos cuentas)»
  1. En Burp, autentícate como A y guarda una petición a un recurso suyo.
  2. Cambia el ID por el de B manteniendo la sesión de A → ¿accedes a datos de B?
  3. Automatiza con Autorize (o AuthMatrix): configuras las cookies/token de un segundo usuario y la extensión repite cada petición con esa sesión, marcando en verde/rojo dónde falla el control. Es la forma más rápida de cubrir toda la app.
  • Enumeración masiva con IDs secuenciales (en un engagement, demuéstralo con unos pocos; no vuelques millones).
  • GraphQL: nodos por id global; prueba acceder a nodos de otros usuarios.
  • Referencias a ficheros/blobs/firmas (URLs de descarga, tokens de documento).
  • Race conditions sobre comprobaciones de propiedad (ver ficha).

Burp Suite (Autorize, AuthMatrix), ffuf para enumeración controlada de IDs, y comparación de respuestas entre sesiones.

Fuga de datos de todos los usuarios, modificación/borrado, escalada a admin y ATO. Encadenable con JWT (forjar user_id), con enumeración (descubrir IDs) y con mass assignment (escribir campos privilegiados).

  • Una cuenta accediendo a muchos objetos distintos en poco tiempo (enumeración).
  • Accesos a objetos que no pertenecen al usuario (requiere registrar identidad + objeto + decisión en el log para poder detectarlo).
  • Llamadas a endpoints de admin por cuentas sin rol; transiciones 403→200 tras manipular parámetros.

Logs de aplicación/API gateway con identidad + objeto accedido + decisión de autorización, y métricas por usuario (nº de objetos únicos accedidos por minuto).

  1. Autorización en servidor por cada petición, ligada a la identidad de la sesión (nunca a parámetros del cliente).
  2. Negar por defecto: todo recurso/función se deniega salvo permiso explícito.
  3. Comprobar propiedad del objeto (WHERE owner_id = :sesion) además del rol.
  4. Centralizar la autorización (un middleware/política, RBAC/ABAC) con tests automatizados por rol; no repartir comprobaciones copiadas por cada controlador.
  5. Referencias indirectas/no adivinables (UUID v4) como capa extra, nunca como sustituto del control.
  6. Contra mass assignment: lista blanca de campos vinculables (DTOs).

Revisar los accesos del atacante, notificar a los afectados según normativa (RGPD), corregir el control (propiedad + rol), e implantar detección de enumeración.

  • First American Financial (2019) — URLs secuenciales a documentos expusieron ~885 millones de registros financieros (BAC roto / IDOR de documentos).
  • USPS “Informed Visibility” (2018) — API con control de acceso roto que exponía datos de ~60 millones de usuarios.
  • Parler (2021) — IDs de publicación secuenciales permitieron archivar prácticamente todo el contenido de la plataforma.
  • Peloton, Experian, T-Mobile y numerosas apps móviles — BOLA/IDOR en APIs es de los hallazgos más frecuentes y mejor pagados en bug bounty.

Broken Access Control es A01 del OWASP Top 10. CVEs en NVD (https://nvd.nist.gov/vuln/search) y GitHub Advisories (https://github.com/advisories).

  • Método de dos cuentas aplicado a lectura y escritura.
  • Probados IDs en URL, cuerpo/JSON, cabeceras y JWT.
  • Probados tipos de ID (secuencial, UUID filtrado, codificado).
  • Escalada vertical: endpoints/métodos de admin con usuario normal.
  • Flujos multi-paso validados en todos los pasos.
  • Mass assignment probado (campos extra tipo role).
  • Impacto demostrado accediendo a un recurso de tu segunda cuenta (sin tocar datos reales de terceros).