⏱️ Lectura: 18 min

En julio de 2026, dos investigadores demostraron que con solo la patente de un auto podían ubicarlo, desbloquearlo y arrancarlo a distancia, sin tocar nunca el vehículo. El fallo no estaba en el hardware, sino en la API del fabricante: el patrón que explotaron (una falla de autorización a nivel de objeto) se repite en cualquier sistema que conecte un objeto físico a una cuenta de usuario. Los investigadores mantienen en secreto la marca hasta que termine de corregir el problema, pero el mecanismo ya es un caso de estudio reutilizable para quien construye o audita plataformas conectadas.

📑 En este artículo
  1. TL;DR
  2. ¿Qué es la autorización a nivel de objeto?
  3. Por qué importa en sistemas IoT y plataformas conectadas
  4. Cómo funciona el patrón: de un dato público a control total
  5. Cómo se reconstruye el mapa de una API desde la app
  6. Ejemplos prácticos: el mismo fallo en una API propia
  7. Comparativa: modelos de autorización frente a este patrón
  8. Casos de uso reales del mismo patrón
  9. Errores comunes y buenas prácticas
  10. Profundizando: BOLA más allá del CRUD simple
  11. Preguntas frecuentes
    1. ¿Qué es BOLA exactamente?
    2. ¿BOLA es lo mismo que IDOR?
    3. ¿Alcanza con usar UUID en vez de IDs secuenciales?
    4. ¿Las claves de API hardcodeadas en una app móvil son parte del mismo problema?
    5. ¿Cómo se diferencia de un fallo de autenticación?
    6. ¿Qué hago si encuentro este fallo en la API de un tercero?
  12. Referencias
    1. 📚 Artículos relacionados

TL;DR

  • Un fallo de autorización a nivel de objeto deja que cualquier usuario autenticado controle recursos de otro con solo cambiar un ID en la URL.
  • La cadena patente, VIN, GUID de suscriptor y cuenta conecta datos públicos con APIs internas sin validar a quién pertenece cada dato.
  • BOLA encabeza el ranking de riesgos de OWASP API Security desde 2019 y sigue ahí en la edición de 2023.
  • Validar la pertenencia del recurso en cada endpoint, no solo la identidad del token, cierra la mayoría de estos casos.
  • Dos cuentas de prueba y un cliente HTTP alcanzan para auditar si tu propia API sufre este mismo patrón.

¿Qué es la autorización a nivel de objeto?

La autorización a nivel de objeto es el control que verifica si quien hace una petición tiene permiso sobre ese recurso puntual, no solo si está autenticado. Sin ese control, basta cambiar un identificador en la URL para acceder a datos de otra cuenta.

El nombre viene del OWASP API Security Top 10, que lo clasifica como BOLA (Broken Object Level Authorization) y lo distingue de un simple fallo de autenticación. Autenticarse responde quién soy; autorizar responde qué puedo tocar yo, específicamente, dentro de todo lo que existe en el sistema. Un servidor puede hacer perfecto lo primero y fallar por completo en lo segundo.

El concepto no es nuevo. La comunidad de seguridad web lo conoce desde hace más de una década como IDOR (Insecure Direct Object Reference). OWASP lo renombró para su guía de APIs porque en una API REST o GraphQL el objeto casi siempre viaja explícito en la URL o en el cuerpo de la petición, lo que vuelve el patrón todavía más fácil de encontrar y de explotar.

El investigador tardó dos semanas en mapear la plataforma de identidad del fabricante. Foto de ThisisEngineering en Unsplash

Por qué importa en sistemas IoT y plataformas conectadas

Un fallo de autorización a nivel de objeto en una tienda online filtra el pedido de otro cliente. El mismo fallo en una plataforma de autos conectados entrega el control físico del vehículo: desbloquearlo, arrancarlo, tocar la bocina o rastrear su ubicación en vivo. El código que falla es idéntico, un endpoint que no valida propietario, pero la consecuencia cambia de categoría por completo.

Por eso OWASP ubica a BOLA en el primer puesto de su API Security Top 10 desde la edición de 2019 y lo mantiene ahí en la revisión de 2023. No es un bug exótico: según ese mismo documento, es la causa más reportada en incidentes reales contra APIs, porque cualquier endpoint que reciba un identificador como parámetro es candidato.

Las plataformas conectadas agravan el problema porque encadenan sistemas con identificadores propios. La app habla con el backend de telemática, ese backend habla con un proveedor de identidad, y el proveedor habla con el sistema que factura al cliente. Cada eslabón es una oportunidad para olvidar repetir la misma pregunta: ¿este usuario tiene permiso sobre este objeto puntual, o solo demostró quién es?

Cómo funciona el patrón: de un dato público a control total

El ataque no empieza robando una contraseña. Empieza reconstruyendo las llamadas que hace la app oficial: se descompila el paquete de la aplicación, se buscan las URLs base y, con eso, el mapa de la API queda a la vista. Esa reconstrucción, por sí sola, no infringe ninguna cuenta ajena todavía; el problema aparece en el paso siguiente.

Con el mapa de endpoints en mano, el patrón avanza en capas. Primero, un dato público (la patente) se convierte en un identificador interno (el VIN) a través de un registro estatal, algo legítimo porque existen usos honestos para esa consulta, como verificar el historial de un auto usado. Segundo, ese identificador interno se cruza contra un endpoint administrativo que, en el caso que documentó la investigación, no exigía más autenticación que una clave de API fija encontrada dentro del propio bundle de JavaScript de la app. Tercero, esa clave entrega un identificador de suscriptor, y el identificador de suscriptor entrega el correo y los datos de cuenta del propietario real. Cuarto, y último, ese correo permite obtener o forzar un token válido en la plataforma de identidad central, el mismo token que la app legítima usa para desbloquear, arrancar o rastrear el auto.

Ningún paso de esa cadena exige una vulnerabilidad de hardware. Cada paso es, por separado, una API que responde correctamente a una pregunta mal planteada: ¿quién tiene este identificador?, en lugar de ¿quién tiene permiso sobre este identificador?. Reemplazá auto por cerradura inteligente, cámara de seguridad o wearable de salud y la cadena es exactamente la misma.

sequenceDiagram
participant At as Atacante
participant Reg as Registro publico
participant Adm as API administrativa
participant Idp as Plataforma de identidad
At->>Reg: consulta la patente
Reg-->>At: devuelve el VIN
At->>Adm: envia el VIN con la clave fija del APK
Adm-->>At: devuelve GUID de suscriptor y email
At->>Idp: solicita sesion con el email obtenido
Idp-->>At: token de acceso valido
Note over At,Idp: el token abre control total del vehiculo

Cómo se reconstruye el mapa de una API desde la app

Antes de encontrar cualquier fallo de autorización hace falta saber qué endpoints existen, y la mayoría de las apps móviles los expone sin querer. Un APK o un IPA se puede descomprimir con herramientas gratuitas (jadx para Android, por ejemplo) y leer como si fuera código fuente casi completo: ahí aparecen las URLs base, los nombres de los parámetros y, en los peores casos, las claves de API incrustadas.

La segunda técnica, más directa, es interceptar el tráfico real con un proxy como mitmproxy o Burp Suite mientras se usa la app normalmente: abrir la app, mirar el auto en el mapa, pedir que suene la bocina. Cada una de esas acciones dispara una petición HTTP que el proxy captura completa, con headers, token y cuerpo incluidos. Repetir esa petición cambiando solo un identificador es, literalmente, todo lo que hace falta para probar si existe un fallo de autorización de API, sin necesidad de ver una sola línea de código del servidor.

Ninguna de las dos técnicas rompe nada: descompilar tu propia app o interceptar tu propio tráfico con una cuenta de prueba es, en la práctica, la misma auditoría que haría un atacante, solo que sin cruzar la línea de tocar cuentas de otra persona. Es, de hecho, el primer paso recomendado antes de contratar un pentest externo. Si el equipo interno no puede reconstruir su propia API desde la app, tampoco va a poder revisar que cada endpoint valide pertenencia.

⚠️ Ojo: una clave de API fija dentro del bundle de una app móvil no es un detalle menor. Cualquiera puede extraerla descompilando el paquete, así que nunca debería ser la única barrera de un endpoint administrativo.

Ejemplos prácticos: el mismo fallo en una API propia

Para ver el patrón sin depender de ningún fabricante, alcanza un endpoint típico de una plataforma de vehículos conectados hecha a medida. Así se ve la versión vulnerable en un backend Node con Express:

app.post('/api/v1/vehicles/:vehicleId/unlock', authenticate, (req, res) => {
  const vehicle = db.vehicles.findById(req.params.vehicleId);
  vehicle.unlock();
  res.json({ status: 'unlocked', vehicleId: vehicle.id });
});

El middleware authenticate confirma que el token es válido, pero nadie confirma que el vehicleId de la URL pertenezca al usuario del token. Un atacante autenticado como usuario A puede llamar al mismo endpoint cambiando el ID por el de un vehículo del usuario B:

curl -X POST https://api.flotaconectada.dev/v1/vehicles/3b7e2f-b2-usuario-b/unlock \
  -H "Authorization: Bearer $TOKEN_DE_USUARIO_A"

La respuesta, en el servidor vulnerable, es un 200 con el auto de otra persona ya desbloqueado:

{"status":"unlocked","vehicleId":"3b7e2f-b2-usuario-b"}

La corrección no agrega una librería nueva ni un servicio externo: agrega una comparación.

app.post('/api/v1/vehicles/:vehicleId/unlock', authenticate, (req, res) => {
  const vehicle = db.vehicles.findById(req.params.vehicleId);
  if (!vehicle || vehicle.ownerId !== req.user.id) {
    return res.status(403).json({ error: 'forbidden' });
  }
  vehicle.unlock();
  res.json({ status: 'unlocked', vehicleId: vehicle.id });
});

Con esa comparación en su lugar, la misma petición del usuario A contra el auto del usuario B devuelve esto:

{"error":"forbidden"}

En forma de diagrama, la decisión que agrega esa línea es siempre la misma, sin importar el framework:

flowchart TD
A["Peticion con object_id"] --> B["Autenticar token"]
B --> C{"El recurso existe?"}
C -- No --> D["404 Not Found"]
C -- Si --> E{"owner_id del recurso es igual al user_id del token?"}
E -- No --> F["403 Forbidden"]
E -- Si --> G["Ejecutar accion"]

Es, literalmente, una línea de más por endpoint. El costo de no escribirla es que cualquier cliente de la API se convierte en administrador de todas las cuentas, no solo de la propia.

Comparativa: modelos de autorización frente a este patrón

No todos los mecanismos de control de acceso a objetos cuestan lo mismo ni escalan igual. Esta tabla resume las opciones más comunes:

Modelo Cuándo usarlo Ventaja Limitación
ID confiado del cliente (antipatrón) Nunca en producción Trivial de implementar Cualquier usuario autenticado accede a cualquier objeto
Chequeo de propietario por endpoint Apps pequeñas o monolitos Bajo costo, fácil de leer en el código Hay que repetirlo en cada handler; un endpoint nuevo puede olvidarlo
Capa de autorización centralizada (middleware o motor de políticas) Microservicios con muchos endpoints Una sola fuente de verdad para toda la API Suma latencia y una pieza más para operar
Modelo relacional de permisos (ReBAC, estilo Zanzibar) Plataformas con jerarquías: flotas, organizaciones, equipos Escala a permisos complejos y herencia Mayor complejidad de diseño desde el día uno
Sam Curry y su equipo documentaron fallas equivalentes en varios fabricantes de autos a comienzos de 2023. Foto de National Cancer Institute en Unsplash

Casos de uso reales del mismo patrón

El caso de la plataforma de autos conectados que documentó la investigación no es aislado. A comienzos de 2023, el investigador Sam Curry publicó, junto a su equipo, una serie de fallas equivalentes en las APIs de varios fabricantes de autos, usando el mismo tipo de cadena: un identificador público o semipúblico (el VIN) que destapaba acceso a cuentas y, desde ahí, a comandos remotos sobre el vehículo.

El patrón tampoco se limita a autos. Cualquier plataforma que conecte un identificador de dispositivo con una cuenta (cerraduras inteligentes, cámaras de seguridad domésticas, flotas de bicicletas o patinetes compartidos, wearables de salud que exponen historiales médicos) repite la misma estructura. Un endpoint recibe un ID y asume, sin verificarlo, que quien lo envía tiene derecho sobre él.

Lo que cambia entre industrias es la gravedad de la consecuencia, no la causa técnica. Un control de acceso a objetos roto en un dispositivo médico conectado puede filtrar un diagnóstico; en una cerradura, puede abrir una puerta física. El código fallido, otra vez, es el mismo endpoint sin un chequeo de pertenencia.

Por eso la lección no depende de la marca anonimizada del caso original: el equipo que mantiene cualquier flota de dispositivos conectados, propios o de terceros integrados por API, puede auditar su propia plataforma con la misma metodología sin esperar a que un investigador externo la publique primero.

Errores comunes y buenas prácticas

La mayoría de estos fallos no nace de negligencia general, sino de una serie de atajos puntuales que se acumulan. Estos son los más frecuentes:

  • Confiar en el ID que manda el cliente: validar el token y asumir que cualquier recurso que ese token pida le pertenece, sin volver a preguntar.
  • IDs secuenciales o adivinables: numerar vehículos, usuarios o pedidos del 1 en adelante facilita enumerar todos los objetos del sistema, aunque exista el chequeo de propiedad.
  • Claves de API fijas en el cliente: cualquier secreto embebido en una app móvil o una SPA es, a efectos prácticos, público. Un endpoint administrativo nunca debería depender solo de eso.
  • Probar solo el camino feliz: los tests de un equipo suelen cubrir el caso de un usuario accediendo a lo suyo y rara vez el caso de un usuario intentando acceder a lo de otro.
  • Herramientas internas sin el mismo rigor: paneles de soporte o administración suelen recibir menos revisión de seguridad que la API de cara al público, pese a tener permisos más amplios.

Las buenas prácticas espejan cada error: usar identificadores no adivinables (UUID v4) como primera capa, exigir que cada handler verifique pertenencia y no solo identidad, rotar y restringir cualquier clave que viva en un cliente, y agregar al menos un test automatizado por endpoint que pruebe el acceso cruzado entre dos cuentas de prueba. Ninguna de estas medidas exige reescribir la arquitectura completa: todas se pueden aplicar endpoint por endpoint, en paralelo al resto del trabajo.

💡 Tip: el test más barato para este patrón es tener dos cuentas de prueba fijas (A y B) en el entorno de CI y correr cada endpoint que reciba un ID con el token de A pero el recurso de B. Si algo responde 200 en vez de 403 o 404, hay un fallo de autorización a nivel de objeto para arreglar antes de mergear.

Profundizando: BOLA más allá del CRUD simple

El ejemplo de un solo endpoint REST es el caso más fácil de explicar, pero no el único donde aparece este fallo. En GraphQL, una sola consulta puede pedir varios objetos en el mismo request mediante un array de IDs. Es común que el resolver valide el primer objeto de la lista, o ninguno, y asuma que el resto comparte el mismo dueño. El resultado es una variante del mismo bug, mucho más difícil de detectar con pruebas manuales porque no hay una sola URL que cambiar, sino un payload JSON con varios campos.

flowchart LR
Q["Consulta GraphQL con 3 object_id"] --> V1["Verifica objeto 1"]
Q --> V2["Verifica objeto 2"]
Q --> V3["Verifica objeto 3 (a veces se omite)"]
V1 --> OK1["Autorizado"]
V2 --> OK2["Autorizado"]
V3 --> FAIL["Sin chequeo: expone datos de otro usuario"]

Vale distinguir este fallo de su primo cercano, la autorización rota a nivel de función (BFLA, Broken Function Level Authorization). BOLA responde si el usuario puede tocar este objeto puntual; BFLA responde si el usuario puede ejecutar esta acción, sin importar el objeto, como un endpoint de borrado que solo debería existir para administradores pero responde igual a cualquier rol. Un mismo sistema puede tener ambos problemas a la vez; las pruebas para uno no cubren al otro, así que conviene probarlas por separado.

También vale separar esto de un fallo de autenticación puro, como una clave de API fija compartida por toda una app. Extraer una clave hardcodeada de un APK, algo que cualquier persona puede hacer con herramientas gratuitas de descompilación, es un problema de gestión de secretos, no de autorización. Pero, como mostró la cadena del caso de autos conectados, ambos fallos suelen combinarse: la clave filtrada abre la puerta, y la falta de chequeo de pertenencia hace que, una vez adentro, no haya ningún muro interno que detenga el movimiento lateral entre cuentas.

Como control adicional, cuando arreglar cada endpoint de inmediato no es viable, el rate limiting por cuenta y la alerta sobre patrones de acceso anómalos (un mismo token pidiendo cientos de IDs distintos en minutos) no cierran el fallo de raíz, pero sí reducen cuánto se puede explotar antes de que alguien lo note. No reemplazan la corrección; la acompañan mientras se despliega.

📖 Resumen en Telegram: Ver resumen

Tu próximo paso: tomá un endpoint real de tu API que reciba un ID por parámetro, armá dos cuentas de prueba y confirmá con una petición cruzada si devuelve 403 o te deja entrar.

📬 Recibí lo nuevo en tu email

Te avisamos de artículos grandes (1-2 por mes).

Preguntas frecuentes

¿Qué es BOLA exactamente?

BOLA (Broken Object Level Authorization) es el nombre que usa OWASP para el fallo en el que una API verifica quién hace la petición, pero no si esa persona tiene permiso sobre el objeto puntual que pide. Aparece cuando el único control es la autenticación del token, no la relación entre el usuario y el recurso.

¿BOLA es lo mismo que IDOR?

Son, en la práctica, el mismo problema con dos nombres de distinta época. IDOR nació en el contexto de aplicaciones web clásicas; BOLA es el término que adoptó OWASP para su API Security Top 10 porque, en una API, el objeto casi siempre viaja explícito en la URL o el payload.

¿Alcanza con usar UUID en vez de IDs secuenciales?

No. Un UUID dificulta adivinar el identificador de otro usuario, pero no reemplaza el chequeo de pertenencia. Si alguien obtiene un UUID ajeno por cualquier otra vía, como un log o un enlace compartido, el fallo de autorización sigue abierto exactamente igual.

¿Las claves de API hardcodeadas en una app móvil son parte del mismo problema?

Son un fallo relacionado pero distinto: una clave fija en el cliente es un problema de gestión de secretos, no de autorización. El patrón BOLA aparece después, cuando esa clave u otro método ya te dejó entrar y nadie vuelve a preguntar si tenés derecho sobre el objeto específico que pedís.

¿Cómo se diferencia de un fallo de autenticación?

La autenticación responde quién eres; el control de acceso a objetos responde qué podés tocar, específicamente, dentro de todo lo que existe en el sistema. Un servidor puede autenticar perfecto y, aun así, dejar que cualquier cuenta válida controle los recursos de las demás.

¿Qué hago si encuentro este fallo en la API de un tercero?

Reportalo por los canales de divulgación responsable del fabricante, como un archivo security.txt, un programa de bug bounty o un correo de seguridad publicado, y dale tiempo razonable para corregirlo antes de publicar detalles técnicos. Es, de hecho, exactamente lo que hicieron los investigadores del caso que inspira este artículo: mantener la marca en secreto hasta que termine de corregir el problema.

Referencias

  • shubs.io: investigación original sobre la cadena de fallas de autorización que permitía controlar autos conectados de un fabricante no revelado.
  • OWASP API Security Top 10: documento que ubica a BOLA en el primer puesto del ranking de riesgos de API desde 2019.
  • CWE-639 (MITRE): definición formal de Authorization Bypass Through User-Controlled Key, la raíz técnica de este patrón.
  • Sam Curry: investigación de 2023 sobre fallas equivalentes en APIs de múltiples fabricantes de autos.

📱 ¿Te gusta este contenido? Únete a nuestro canal de Telegram @programacion donde publicamos a diario lo más relevante de tecnología, IA y desarrollo. Resúmenes rápidos, contenido fresco todos los días.

Imagen destacada: Foto de Sasun Bughdaryan en Unsplash

¿Te sirvió? ¿Te dio otro error? Contalo abajo: las preguntas se responden y le sirven al siguiente que llegue.

Dejar un comentario

Andrés Morales

Desarrollador e investigador en inteligencia artificial. Escribe sobre modelos de lenguaje, frameworks, herramientas para devs y lanzamientos open source. Cubre papers de ML, ecosistema de startups tech y tendencias de programación.

0 Comentarios

Deja un comentario

Marcador de posición del avatar

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *

Podés incluir código entre <code>…</code> o, para varias líneas, <pre><code>…</code></pre>.

Este sitio usa Akismet para reducir el spam. Aprende cómo se procesan los datos de tus comentarios.