Qué es BOLA (IDOR): la vulnerabilidad número uno de las APIs, con ejemplos y cómo evitarla
Por Kike Gandia · Co-Fundador y CEO, OSCP
BOLA (Broken Object Level Authorization) es el fallo que ocurre cuando una API comprueba quién eres, pero no si el objeto que pides es tuyo. Basta con cambiar un identificador en la petición —el número de una factura, el ID de un pedido, el de un usuario— para leer, modificar o borrar datos de otra persona. Es el riesgo número uno del OWASP API Security Top 10 y la versión moderna de lo que durante años se llamó IDOR (Insecure Direct Object Reference). En esta guía verás qué diferencia hay entre los dos términos, cómo se ve en peticiones reales, por qué los escáneres casi nunca lo encuentran, cómo se prueba y qué medidas lo corrigen de verdad.
Qué es BOLA y qué es IDOR
Una API recibe una petición autenticada —con una sesión, un token o una clave válidos— que incluye el identificador de un objeto: GET /api/v1/facturas/1043. Si el servidor comprueba que el token es válido pero no que la factura 1043 pertenece al usuario o a la empresa del token, cualquier usuario registrado puede pedir la 1044, la 1045 y todas las demás. Eso es un BOLA.
La definición formal tiene tres piezas:
- El atacante está autenticado o la funcionalidad es pública: no necesita robar credenciales de nadie, le basta con su propia cuenta.
- El objeto se identifica con un valor que controla el cliente: un ID en la ruta, un parámetro, un campo del cuerpo, una cabecera.
- Falta la comprobación de autorización a nivel de objeto: el servidor no verifica que ese usuario puede realizar esa acción sobre ese objeto concreto.
En la clasificación de debilidades de MITRE corresponde a CWE-639, «Authorization Bypass Through User-Controlled Key», y en el OWASP API Security Top 10 de 2023 es API1:2023. El impacto va desde la exposición de datos de otros usuarios hasta su modificación o borrado y, en los peores casos, la toma de control de cuentas.
BOLA vs IDOR: ¿son lo mismo?
En la práctica se usan como sinónimos, y un pentester que reporta uno u otro está hablando del mismo fallo. La diferencia es de origen y de enfoque:
| Aspecto | IDOR | BOLA |
|---|---|---|
| Nombre completo | Insecure Direct Object Reference | Broken Object Level Authorization |
| Origen | Categoría del OWASP Top 10 de aplicaciones web en sus primeras ediciones; hoy forma parte de Broken Access Control | Riesgo número uno del OWASP API Security Top 10 desde su primera edición, de 2019 |
| Pone el foco en | La referencia: el identificador que se expone y se puede manipular | La causa: la falta de comprobación de autorización sobre el objeto |
| Contexto habitual | Aplicaciones web clásicas | APIs REST, GraphQL, móviles y microservicios |
El cambio de nombre no es cosmético. «Referencia directa insegura» invita a pensar que el problema es el identificador y que se arregla ocultándolo o haciéndolo impredecible. «Autorización rota a nivel de objeto» deja claro dónde está el fallo y dónde la solución: en el servidor, en cada acceso a cada objeto.
Cómo se ve un BOLA en peticiones reales
El identificador vulnerable puede viajar en cualquier parte de la petición, y no siempre es un número:
| Dónde está el identificador | Ejemplo | Qué consigue el atacante |
|---|---|---|
| Ruta | GET /api/v1/pedidos/58213 | Ver pedidos, direcciones y teléfonos de otros clientes |
| Parámetro de consulta | GET /api/documentos?clienteId=311 | Descargar documentos de otra empresa |
| Cuerpo de la petición | POST /api/transferencias con "cuentaOrigen": "ES91…" | Ordenar operaciones sobre la cuenta de otro |
| Cabecera | X-Tenant-Id: 27 | Saltar a los datos de otro cliente en un SaaS multi-tenant |
| Recurso anidado | GET /api/empresas/12/empleados/88 | Leer un empleado de otra empresa porque solo se comprueba la empresa de la ruta |
| GraphQL | query con order(id: "…") | Lo mismo que en REST, a menudo en resolvers anidados que nadie revisó |
| Ficheros | GET /descargas/contratos/2024-117.pdf | Descargar contratos o justificantes ajenos |
| Operaciones de escritura | PUT, PATCH o DELETE sobre /api/direcciones/9921 | Modificar o borrar datos de otro usuario |
| Operaciones por lotes | GET /api/facturas?ids=1001,1002,1003 | Extraer cientos de objetos en una sola petición |
Dos variantes merecen atención especial. Las de escritura, porque el impacto pasa de la confidencialidad a la integridad: cambiar el correo de otra cuenta suele acabar en la toma de control de esa cuenta. Y las multi-tenant, en las que el objeto pertenece a una organización cliente: un solo BOLA expone a todos los clientes de la plataforma a la vez.
Por qué es tan frecuente
Ningún equipo decide no comprobar la autorización. BOLA aparece por cómo se construyen las APIs:
- Los frameworks resuelven la autenticación, no la propiedad. Un middleware valida el token en todas las rutas; comprobar que el pedido 58213 es del usuario depende del modelo de negocio y hay que escribirlo endpoint a endpoint.
- Las pruebas se hacen con un solo usuario. El desarrollador prueba con su cuenta, ve sus datos y todo funciona. Sin un segundo usuario, el fallo es invisible.
- Los identificadores viajan al cliente. La app móvil o la SPA necesitan los IDs para pedir los objetos, así que el atacante los ve y puede cambiarlos.
- Los microservicios confían en quien los llama. El gateway autentica y el servicio interno asume que, si la petición ha llegado, está autorizada para cualquier objeto.
- Los recursos anidados y las rutas nuevas se olvidan. Se protege GET /pedidos/{id} y se añade después GET /pedidos/{id}/factura sin la misma comprobación.
- El acceso directo a la base de datos desde el cliente. En plataformas tipo backend como servicio, si las políticas de seguridad a nivel de fila no están activadas o están mal escritas, el resultado es un BOLA a escala de toda la base de datos. Es uno de los fallos que más repiten las aplicaciones generadas con IA.
Por qué los escáneres casi nunca lo encuentran
Para un escáner automático, una respuesta 200 con datos es una respuesta correcta. No sabe que el pedido 58213 pertenece a otro cliente, porque eso es lógica de negocio, no un patrón técnico como una inyección o una cabecera que falta.
Algunas herramientas permiten configurar dos sesiones y comparar respuestas, y ayudan en APIs pequeñas y bien documentadas. Pero siguen necesitando que alguien defina qué objetos pertenecen a quién, qué roles existen y qué debe ver cada uno, y fallan en los casos más interesantes: identificadores que solo aparecen en respuestas de otros endpoints, objetos anidados, operaciones de escritura con efectos laterales u objetos compartidos de forma legítima entre usuarios.
Por eso BOLA es, a la vez, el fallo más frecuente en los pentests de APIs y uno de los que más se escapan a los análisis automáticos que las empresas ya tienen.
Cómo se prueba un BOLA
La prueba es metódica más que sofisticada. Lo esencial es tener al menos dos usuarios de cada rol, idealmente en dos organizaciones distintas si la aplicación es multi-tenant, y recorrer toda la API con los dos:
| Paso | Qué se hace | Qué se busca |
|---|---|---|
| Mapear | Recorrer la aplicación con el usuario A capturando todas las peticiones, o partir de la especificación OpenAPI | Todos los endpoints que reciben un identificador |
| Recolectar identificadores | Anotar los IDs de objetos del usuario B que aparecen en respuestas, enlaces compartidos, exportaciones o correos | Identificadores válidos de objetos ajenos, aunque no sean predecibles |
| Cruzar | Repetir cada petición de A sustituyendo sus identificadores por los de B, con el token de A | Respuestas con datos o efectos sobre objetos de B |
| Todos los métodos | Probar lectura, modificación y borrado, no solo GET | BOLA de escritura, de mayor impacto |
| Sin sesión | Repetir las peticiones sin token o con un token caducado | Endpoints que deberían requerir autenticación y no la piden |
| Comparar respuestas | Distinguir 403, 404, 200 vacío y 200 con datos | Comprobaciones parciales o filtrado solo en la respuesta |
Las extensiones de proxies de interceptación que reenvían cada petición con la sesión de otro usuario automatizan buena parte del cruce, pero la interpretación sigue siendo manual: hay objetos que se comparten legítimamente y respuestas que parecen correctas y no lo son.
La guía de pruebas de OWASP recoge este procedimiento como WSTG-ATHZ-04, «Testing for Insecure Direct Object References».
Un detalle que se pasa por alto: un identificador no predecible, como un UUID, no elimina el BOLA. Solo cambia la pregunta de «¿puedo adivinar el ID?» a «¿puedo conseguir el ID?», y la respuesta suele ser sí: aparece en otras respuestas de la API, en URLs compartidas, en notificaciones o en los logs del navegador.
Casos reales
El caso más documentado de este fallo es el de First American Financial, una aseguradora de títulos de propiedad estadounidense, porque la SEC publicó su investigación con detalle:
| Aspecto | Qué dice la fuente oficial |
|---|---|
| El fallo | Los documentos de su aplicación web EaglePro se servían en URLs con un número de documento secuencial; cambiando los dígitos de la URL se veían documentos de otras operaciones |
| Lo expuesto | Más de 800 millones de imágenes de documentos, algunas desde 2003, con datos personales y financieros |
| Cuándo se supo | Su propio equipo de seguridad lo había detectado meses antes, en un pentest interno de enero de 2019; en mayo de 2019 un periodista especializado en ciberseguridad avisó a la empresa y el caso se hizo público |
| Sanción de la SEC (2021) | 487.616 dólares, no por la vulnerabilidad en sí, sino porque la información no llegó a los directivos responsables de lo que la empresa comunicaba al mercado |
| Sanción del NYDFS (2023) | 1 millón de dólares por incumplir la normativa de ciberseguridad del regulador financiero de Nueva York |
Es un IDOR clásico en una aplicación web, no en una API, pero el mecanismo es exactamente el mismo. Y deja dos lecciones que van más allá de lo técnico: el fallo se encontró meses antes de hacerse público, así que el problema no fue detectarlo sino priorizarlo y corregirlo; y un BOLA que expone datos de clientes es un asunto de dirección, no solo del equipo de desarrollo.
Hay incidentes en APIs de gran escala de los que no se conoce el mecanismo exacto. En enero de 2023, T-Mobile comunicó a la SEC que un atacante había obtenido datos de unos 37 millones de cuentas de clientes «a través de una única API sin autorización», sin detallar el tipo de fallo. Son la norma más que la excepción: las comunicaciones oficiales rara vez explican la causa técnica, y por eso conviene desconfiar de las listas de «brechas por IDOR» que circulan sin fuentes.
Cómo se corrige de verdad
La corrección tiene que estar en el servidor, en cada acceso a cada objeto. Estas medidas, de más a menos importantes:
| Medida | Qué resuelve | Qué no resuelve |
|---|---|---|
| Comprobación de autorización por objeto en una capa central | Garantiza que cada lectura y escritura verifica usuario, objeto y acción | Nada si hay endpoints que no pasan por esa capa |
| Consultas acotadas al usuario o al tenant | Buscar el pedido con su ID y el del usuario actual a la vez, de modo que un ID ajeno simplemente no existe | Objetos compartidos entre usuarios, que requieren una regla explícita |
| Seguridad a nivel de fila en la base de datos | Una segunda barrera aunque la aplicación olvide un filtro | Lógica de autorización compleja que no se expresa bien en políticas de la base de datos |
| Endpoints sin identificador para los recursos propios | GET /api/me/perfil en lugar de GET /api/usuarios/77 elimina el parámetro manipulable | Recursos que el usuario sí debe poder elegir |
| Identificadores no predecibles (UUID) | Dificultan la enumeración masiva | No sustituyen a la comprobación: el ID se puede filtrar |
| Respuesta uniforme | Devolver 404 tanto si el objeto no existe como si no es tuyo evita confirmar qué IDs existen | El fallo de fondo, si la comprobación falta |
| Detección de enumeración | Alertar ante muchas peticiones a identificadores consecutivos o a objetos ajenos | Ataques lentos o dirigidos a pocos objetos |
La regla de diseño que más BOLA evita es denegar por defecto: si un endpoint nuevo no declara su política de acceso, no se publica. Y la que más ayuda a revisarlo: que la comprobación tenga un nombre buscable en el código, en lugar de condiciones repartidas por cada controlador.
Cómo evitar que vuelva: pruebas y revisión
Un BOLA corregido vuelve con facilidad en el siguiente endpoint. Lo que funciona para evitarlo:
- Tests de autorización en el pipeline. Para cada endpoint que recibe un identificador, un test que crea dos usuarios y comprueba que A no puede leer, modificar ni borrar lo de B. Es barato, rápido y detecta la regresión antes de producción.
- Revisión de código con una pregunta fija. En cada pull request que añade o cambia un endpoint: ¿dónde se comprueba que este objeto es de este usuario?
- Inventario de endpoints. Una especificación OpenAPI al día permite saber qué endpoints reciben identificadores y comprobar que todos tienen su test.
- Atención a los hermanos de BOLA. El OWASP API Top 10 tiene otros dos riesgos de autorización: a nivel de propiedad (campos que no deberían devolverse o aceptarse) y a nivel de función (endpoints de administración accesibles para usuarios normales). Se prueban igual, con varios usuarios y roles.
- Pentest tras cambios de modelo de acceso. Nuevos roles, cuentas compartidas, multi-tenancy, una API para partners o una app móvil nueva son los momentos en que aparecen más BOLA.
FAQ
¿BOLA e IDOR son lo mismo?
En la práctica, sí: describen el mismo fallo. IDOR es el nombre clásico de las aplicaciones web y pone el foco en el identificador que se manipula; BOLA es el nombre del OWASP API Security Top 10 y pone el foco en la causa, la falta de comprobación de autorización sobre el objeto.
¿Usar UUID en lugar de IDs numéricos evita el BOLA?
No. Dificulta adivinar identificadores, pero no autoriza nada: si el atacante obtiene el UUID de un objeto ajeno —en otra respuesta de la API, un enlace compartido o una notificación—, el fallo sigue ahí. Es una medida complementaria, nunca la corrección.
¿Por qué nuestro escáner de vulnerabilidades no lo ha detectado?
Porque para detectarlo hay que saber a quién pertenece cada objeto, y eso es lógica de negocio. Para un escáner, una respuesta con datos es una respuesta correcta. Se detecta probando con al menos dos usuarios por rol y cruzando sus identificadores en todos los endpoints.
¿Qué severidad tiene un BOLA?
Depende de qué datos expone y de si permite escribir. Un BOLA de lectura sobre datos personales o financieros, o cualquiera que permita modificar o borrar datos ajenos o tomar el control de cuentas, suele clasificarse como alto o crítico. Uno sobre datos poco sensibles y no enumerables puede ser medio.
Si encontramos un BOLA, ¿tenemos que notificarlo a la AEPD?
Solo si hubo una brecha: si alguien no autorizado accedió a datos personales, el RGPD obliga a notificarla en 72 horas salvo que sea improbable que suponga un riesgo para las personas. Si el fallo se detecta en un pentest y los registros muestran que nadie lo explotó, no hay brecha que notificar, aunque conviene documentar el análisis. Sin registros suficientes, esa conclusión es mucho más difícil de sostener.
¿Cómo lo prevenimos en el desarrollo sin frenar al equipo?
Con una capa de autorización centralizada, consultas que siempre incluyen al usuario o al tenant actual y un test automático de dos usuarios por endpoint en el pipeline. Son cambios pequeños si se adoptan pronto y evitan la mayoría de los BOLA antes de que lleguen a producción.
Servicio relacionado
pentesting de APIs con pruebas de autorización por usuario y rol
Contenido relacionado
- OWASP API Security Top 10 explicado
- Seguridad de JWT y OAuth en APIs
- BOLA en GraphQL: vulnerabilidades comunes
- IDOR y aislamiento multi-tenant en SaaS
- Supabase sin RLS: el BOLA de las apps hechas con IA
- Pentesting de aplicaciones SaaS