La mayoría de las aplicaciones resuelve bien la autenticación: exige un usuario y una contraseña, quizá un segundo factor, y con eso confirma quién es la persona que entra. El problema aparece un paso después, cuando el sistema debe decidir qué puede hacer esa persona una vez dentro. Ahí es donde falla el control de acceso, y ahí se concentra la vulnerabilidad más extendida de la web actual.
El proyecto OWASP ubica al Broken Access Control (control de acceso roto) en el primer lugar de su Top 10, y sus mediciones más recientes son elocuentes: prácticamente todas las aplicaciones evaluadas presentaron alguna forma de control de acceso deficiente. No se trata de un caso de borde, sino de un patrón que atraviesa a casi cualquier sistema con usuarios y permisos.
En este artículo revisaremos en qué consiste la vulnerabilidad, sus formas más comunes, cómo se explota tanto en aplicaciones web como en APIs, y por qué su impacto varía según el negocio. Al final veremos cómo mitigarla y qué papel cumple un sistema de control de acceso basado en roles (RBAC).
Autenticación y autorización no son lo mismo
Conviene partir por una distinción que suele diluirse. La autenticación verifica la identidad, es decir, confirma que alguien es quien dice ser. La autorización, en cambio, determina qué recursos y operaciones tiene permitido usar esa identidad ya verificada. Son controles distintos y secuenciales: primero se autentica, luego se autoriza.
El control de acceso es la implementación de esa autorización, y solo es efectivo cuando se aplica en código de servidor de confianza (o en funciones serverless equivalentes), donde el atacante no puede alterar ni la verificación ni los metadatos en que se apoya. Cualquier control que viva únicamente en el navegador, como ocultar un botón o deshabilitar un campo, mejora la experiencia de uso, pero no protege nada: es una decisión de interfaz, no de seguridad.
El control de acceso roto, entonces, se produce cuando la aplicación no restringe correctamente lo que un usuario autenticado, o incluso uno anónimo, puede ver o hacer. Sus consecuencias habituales son la divulgación de información a terceros no autorizados, la modificación o destrucción de datos, y la ejecución de funciones de negocio fuera del alcance previsto.
En qué consiste la vulnerabilidad
Un control de acceso correcto aplica una política de modo que los usuarios no puedan actuar fuera de los permisos previstos. La vulnerabilidad surge cuando esa política falla por una de dos razones: o bien la aplicación confía en un dato que el usuario controla (un identificador, un rol embebido en un token, una URL), o bien omite la verificación por completo en algún punto del flujo.
OWASP asocia esta categoría a numerosas debilidades (CWE), entre ellas la autorización ausente (CWE-862, Missing Authorization), la autorización incorrecta (CWE-863) y el bypass de autorización mediante una clave controlada por el usuario (CWE-639). Su carácter transversal explica por qué encabeza el ranking: no es un error puntual, sino una familia de fallas de lógica que se manifiesta de muchas maneras.
Las formas del control de acceso roto
Escalamiento de privilegios: vertical y horizontal
El escalamiento vertical ocurre cuando un usuario obtiene privilegios superiores a los que le corresponden (por ejemplo, un usuario común que accede a funciones administrativas), o cuando alguien actúa como usuario autenticado sin haber iniciado sesión. El escalamiento horizontal, en cambio, mantiene el mismo nivel de privilegio pero cruza la frontera entre pares: un usuario que accede a los datos o acciones de otro usuario equivalente.
Referencias directas inseguras a objetos: IDOR y BOLA
Esta es, probablemente, la forma más frecuente. En el mundo web se la conoce como IDOR (Insecure Direct Object Reference): la aplicación expone el identificador de un objeto (una cuenta, una factura, un documento) y confía en él sin verificar que pertenezca a quien lo solicita. Basta con cambiar ese identificador en la URL o en un parámetro para acceder a lo ajeno.
En el ámbito de las APIs, la misma falla recibe el nombre de BOLA (Broken Object Level Authorization) y encabeza el OWASP API Security Top 10. Es especialmente prevalente porque el servidor de una API no suele mantener el estado completo del cliente: se apoya en los identificadores de objeto que llegan en cada petición, sean enteros secuenciales, UUID o cadenas genéricas. Si el backend no comprueba la propiedad del objeto en cada acceso, el atacante solo debe modificar ese identificador en la URL, la query string, una cabecera o el cuerpo de la solicitud.
A nivel de debilidad, corresponde al bypass de autorización mediante una clave controlada por el usuario (CWE-639). Usar identificadores aleatorios e impredecibles, como los GUID, eleva la dificultad de enumeración, pero no reemplaza la verificación de autorización: es una medida de defensa en profundidad, no el control en sí.
Autorización a nivel de función: endpoints sin control y BFLA
Un segundo grupo de fallas no está en el objeto, sino en la función. Es común encontrar APIs con controles ausentes para operaciones POST, PUT o DELETE, o endpoints administrativos accesibles por navegación forzada (forced browsing), adivinando o infiriendo una URL privilegiada. En la clasificación de APIs esto se conoce como BFLA (Broken Function Level Authorization). La distinción con BOLA es útil: BOLA es acceder a un objeto que no corresponde; BFLA es invocar una función a la que no se debería llegar en absoluto, como cuando un usuario común ejecuta DELETE /admin/users/5.
Manipulación de metadatos: tokens, cookies y campos ocultos
Otra vía consiste en alterar los metadatos que la aplicación usa para decidir. Entra aquí el reenvío o la manipulación de un token JWT, de una cookie o de un campo oculto para elevar privilegios, así como el abuso de una invalidación de JWT mal implementada. Si el rol o el tenant viajan en un token que el servidor no valida con rigor, ese token se convierte en la llave.
Otras variantes
El control de acceso roto también abarca el path traversal, es decir, el acceso a archivos fuera del directorio permitido (CWE-22); las configuraciones CORS permisivas, que habilitan el consumo de la API desde orígenes no confiables; y la asignación masiva de propiedades (mass assignment), en que el cliente envía campos adicionales, como role=admin, que el servidor vincula al modelo sin filtrarlos.
Cómo se explota, en web y en API
En la web
Las técnicas más habituales son directas: la manipulación de parámetros (cambiar acct=12345 por otro valor), la navegación forzada a rutas como /admin, la alteración de cookies o de tokens JWT, la modificación de campos ocultos del formulario y el cambio del verbo HTTP, por ejemplo pasar de GET a PUT sobre un recurso que solo debía leerse. Un detalle recurrente: cuando el control vive solo en el frontend, una simple llamada con curl lo omite por completo.
En las APIs
Las APIs concentran hoy buena parte de la superficie de ataque. La explotación de BOLA consiste en enumerar o sustituir identificadores de objeto; la de BFLA, en invocar endpoints privilegiados o alternar el método HTTP; y el mass assignment, en inyectar propiedades que el backend no debería aceptar. Su naturaleza sin estado agrava el problema: al depender de los identificadores que llegan en la petición, cualquier verificación omitida queda expuesta. Un flujo típico se ve así:
GET /api/v1/invoices/1001 → 200 OK · tu factura
GET /api/v1/invoices/1002 → 200 OK · la de otro cliente ← BOLA
DELETE /api/v1/users/5 → 204 · sin ser administrador ← BFLA
En los tres casos el servidor respondió a una operación que jamás debió autorizar.
El impacto depende del negocio
Una característica particular de esta vulnerabilidad es que su gravedad no se mide en el código, sino en lo que ese objeto o esa función representan para el negocio. El mismo defecto técnico, un identificador sin verificar, puede ser un incidente menor o uno crítico según el dominio.
Servicios financieros (fintech y banca)
Aquí el objeto suele ser una cuenta, una transferencia o una cartola. Un IDOR o un BOLA puede traducirse en acceso a cuentas ajenas, transferencias no autorizadas, exposición masiva de datos personales y, en el peor caso, toma de control de cuentas. A la pérdida directa se suman las obligaciones regulatorias y el escrutinio del supervisor.
Salud
En salud, los objetos son historias clínicas, exámenes y recetas: datos personales sensibles por definición. Una falla de autorización expone información de salud de terceros, con consecuencias para la privacidad de las personas y para el cumplimiento normativo. En Chile, la Ley 21.719 trata los datos de salud como una categoría especialmente protegida.
SaaS multi-tenant
En plataformas multi-tenant, el escenario más temido es el acceso entre tenants: que un cliente vea o modifique los datos de otro. Más allá del dato en sí, compromete la promesa central del servicio, que es el aislamiento, y con ella la confianza y los contratos.
Comercio electrónico y retail
Pedidos, direcciones, cupones y datos de venta son objetos igualmente sensibles. OWASP documenta un caso ilustrativo: una API que exponía las ventas por tienda mediante un patrón de URL predecible, lo que permitía recolectar de forma automatizada los datos de miles de comercios.
En síntesis, un mismo hallazgo puede priorizarse de maneras muy distintas, y por eso su evaluación exige entender el contexto del negocio, no solo el defecto técnico.
Cómo mitigar el control de acceso roto
No existe una única contramedida, sino un conjunto de prácticas que se refuerzan entre sí.
Denegar por defecto
Salvo los recursos públicos, todo debe estar denegado por defecto. El acceso se concede de forma explícita para capacidades, roles o usuarios concretos; nunca se asume.
Aplicar la autorización solo en el servidor
Las verificaciones deben ejecutarse del lado del servidor, en el gateway o en la función serverless, donde el atacante no puede alterarlas. El control en el cliente es admisible para la experiencia de uso, jamás como decisión de seguridad.
Centralizar la lógica de autorización
La autorización debe implementarse una vez y reutilizarse en toda la aplicación, mediante mecanismos transversales como middleware o filtros, en lugar de repetir la comprobación método por método. Un solo control olvidado basta para abrir una brecha. La mayoría de los frameworks ofrece piezas para esto, como Spring Security, el middleware de Django, los filtros de .NET o el middleware de Laravel.
Verificar en cada petición, cada verbo y cada recurso
El control debe cubrir todos los métodos HTTP (GET, POST, PUT, DELETE) y también los recursos estáticos, como los archivos en almacenamiento de objetos, que suelen quedar fuera de la política.
Comprobar la propiedad del objeto (contra IDOR y BOLA)
El modelo debe imponer la propiedad del registro en lugar de permitir operar sobre cualquiera. Hay tres estrategias complementarias: recuperar el objeto a partir de la identidad autenticada, y no de un identificador arbitrario del cliente; usar referencias indirectas por sesión; y realizar una comprobación explícita de autorización en cada acceso. Verificar la autorización en toda función que consulte registros a partir de una entrada del cliente es la regla de oro.
Endurecer tokens y sesiones
Los identificadores de sesión con estado deben invalidarse en el servidor tras el cierre de sesión. Los JWT sin estado deben ser de vida corta para acotar la ventana de abuso, y para sesiones más largas conviene apoyarse en refresh tokens y en los estándares de OAuth para revocar el acceso. Todo claim que influya en la autorización debe validarse en el servidor.
Reducir la superficie y observar
Conviene minimizar el uso de CORS, deshabilitar el listado de directorios y evitar que metadatos como .git o los respaldos queden accesibles bajo la raíz web. En paralelo, registrar los fallos de autorización, alertar ante intentos repetidos y aplicar límites de tasa (rate limiting) reduce el daño del abuso automatizado.
Probarlo, y no solo con pruebas unitarias
La autorización debe cubrirse con pruebas unitarias y de integración: denegación por defecto, todos los verbos, salida segura ante fallos. Ahora bien, conviene ser claro: esas pruebas detectan errores temprano, pero no reemplazan una evaluación dedicada. El control de acceso roto es una falla de lógica de negocio, no una firma que un escáner reconozca; requiere de alguien que entienda el dominio para probar cada combinación de rol y objeto.
RBAC: qué es un sistema de control de acceso basado en roles
Buena parte de la mitigación anterior se apoya en un modelo de autorización claro. El más difundido es el control de acceso basado en roles (RBAC, Role-Based Access Control).
Su idea central es sencilla: en lugar de asignar permisos directamente a cada usuario, se asignan permisos a roles y roles a usuarios. Un permiso es una operación autorizada sobre un recurso, por ejemplo "leer facturas" o "eliminar usuarios". Un rol es un conjunto de permisos asociado a una función: cliente, operador, auditor o administrador. El usuario hereda los permisos de los roles que se le otorgan.
Este modelo se rige por dos principios. El mínimo privilegio indica que cada rol debe tener solo los permisos indispensables para su función. La separación de funciones (separation of duties) evita concentrar en un mismo rol capacidades que, combinadas, resulten peligrosas. RBAC admite además variantes: jerárquico, cuando los roles heredan permisos de otros, y con restricciones, cuando se imponen reglas de exclusión entre roles.
La ventaja de RBAC es que centraliza y hace auditable la autorización: los permisos dejan de estar dispersos y pasan a un esquema explícito y revisable. Conviene, eso sí, tener presente una limitación importante: RBAC opera a nivel de función y de rol, no de objeto. Por sí solo no impide un IDOR o un BOLA, que son fallas de nivel de objeto; un usuario con el rol correcto todavía puede acceder al objeto equivocado si no se verifica la propiedad. Por eso RBAC debe complementarse con la comprobación de propiedad descrita antes.
Cuando la lógica de permisos supera lo que los roles pueden expresar con comodidad, o cuando el número de roles crece sin control (un fenómeno conocido como explosión de roles), existen modelos más granulares. El ABAC (Attribute-Based Access Control) decide según atributos del usuario, del recurso y del entorno: hora, ubicación, dispositivo, propiedad del dato. El ReBAC (Relationship-Based Access Control) concede acceso según la relación entre entidades, por ejemplo "creador de este documento". En la práctica, muchos sistemas combinan RBAC para el control grueso de funciones con verificaciones de propiedad o de atributos para el control fino de objetos.
En resumen
El control de acceso roto encabeza el OWASP Top 10 no por ser sofisticado, sino por ser transversal y silencioso: rara vez lo delata una alerta, porque el sistema responde con normalidad a una operación que, simplemente, no debió autorizar. Mitigarlo exige denegar por defecto, centralizar la autorización en el servidor, verificar la propiedad de cada objeto y sostener un modelo de roles bien definido.
Y como es una falla de lógica, se descubre poniéndose en el lugar de un atacante que entiende el negocio: probando, de forma sistemática, qué ve y qué puede hacer cada rol sobre cada objeto. Ese es, precisamente, el tipo de validación que un ejercicio de seguridad ofensiva bien conducido está pensado para encontrar.