Autorización a nivel de objeto, explicada
@programacionLo esencial
- Autorización a nivel de objeto (BOLA) es cuando una API nunca verifica si el usuario es dueño del recurso que pide.
- Un investigador encadenó placa, VIN y GUID de suscriptor hasta llegar al email y al token de cualquier conductor.
- OWASP la clasifica como API1 en su Top 10 de seguridad de APIs: la categoría más reportada en apps conectadas.
- La prueba es simple: pedí un recurso ajeno con tu propio token válido y fijate si la API responde o te bloquea.
- Corregirla no exige infraestructura nueva: alcanza con comparar el dueño real del recurso contra el usuario autenticado.
Qué es la autorización a nivel de objeto
Una API puede exigir login perfecto y aun así fallar por completo. Eso pasa con la autorización a nivel de objeto, conocida en inglés como BOLA (Broken Object Level Authorization). El servidor confirma que el token es válido, pero nunca pregunta si ese token tiene permiso sobre el recurso específico que se pide.
La OWASP API Security Top 10 la ubica en el primer puesto desde su primera edición. La razón es simple: casi toda API moderna identifica recursos por un ID en la URL (un VIN, un GUID, un número de cuenta), y es fácil olvidar revalidar la propiedad de ese ID en cada endpoint nuevo.
El patrón de ataque, paso a paso
El caso documentado por el investigador de seguridad Shubham Shah junto a Sam Curry, publicado en shubs.io, ilustra el patrón completo sin necesidad de tocar una sola pieza de hardware del auto.
La cadena fue: una placa pública se convierte en VIN a través de un registro estatal de vehículos. Ese VIN se convierte en el GUID del suscriptor mediante un endpoint de la API de telemática. Con ese GUID, otro endpoint entrega la cuenta completa, incluido el email registrado en la plataforma de identidad del fabricante. Cuatro llamadas, cero validación de que quien preguntaba fuera el dueño real del auto.
Ninguno de esos pasos, por separado, es ilegal ni inusual: consultar un VIN a partir de una placa es una práctica legítima para revisar el historial de un auto usado. El problema aparece cuando la API encadena esos datos públicos con datos privados sin pedir nunca una prueba de propiedad.
Por qué pasa: las APIs confían en el cliente
La falla casi nunca nace de un error de criptografía o de una contraseña débil. Nace de una suposición implícita: "si el frontend solo muestra los autos del usuario logueado, el backend no necesita revisarlo de nuevo". Pero un atacante no usa el frontend: decompila el APK, reconstruye las peticiones HTTP y las lanza directo contra el backend con cualquier ID que quiera probar.
En el caso de este fabricante, parte de la superficie expuesta ni siquiera requería ese esfuerzo: una herramienta administrativa interna (un "admin tool") quedó accesible en un subdominio público y usaba API keys embebidas en el bundle de JavaScript del propio panel, visibles para cualquiera que abriera las herramientas de desarrollador del navegador.
El caso real: de una placa a cualquier auto
Una vez resuelto el email del dueño, faltaba el paso final: emitir un token de autenticación válido para esa cuenta sin su contraseña. Los investigadores atacaron la plataforma de identidad central del fabricante, construida sobre el software de ForgeRock (OpenAM/OpenIDM), que gestiona el login de toda la app móvil.
Con un token minteado para cualquier cuenta, la API de telemática deja de preguntar quién sos: acepta comandos de desbloqueo, bocina y motor para el vehículo asociado a ese token. El resultado práctico: a partir de una placa visible en la calle, era posible controlar remotamente ese auto específico, en la mayoría de los países donde el fabricante opera esa plataforma.
Cómo detectarlo si auditás tu propia API
Auditar BOLA no requiere herramientas exóticas. La prueba estándar es: autenticate con tu propia cuenta de prueba, y luego pedí un recurso que le pertenece a otra cuenta, cambiando solo el identificador en la URL o en el body.
# Cuenta A autenticada, pidiendo el vehiculo de la cuenta B
curl -X GET https://api.flota-conectada.com/v1/vehicles/VIN_DE_LA_CUENTA_B/status \
-H "Authorization: Bearer $TOKEN_CUENTA_A"
# Si responde 200 con datos reales en vez de 403/404, hay BOLASi el servidor devuelve datos de un recurso que no le pertenece al token usado, la falla existe sin importar qué tan robusto sea el login. Esto hay que repetirlo en cada endpoint que recibe un ID como parámetro: no basta con probarlo una vez en el endpoint principal.
Cómo corregirlo en el código
La corrección no cambia la arquitectura: agrega una comparación explícita entre el dueño registrado del recurso y el usuario que hace la petición, en cada endpoint, sin excepciones.
// Vulnerable: valida el token pero no la propiedad del recurso
app.get('/v1/vehicles/:vin/unlock', authenticate, (req, res) => {
const vehicle = vehicleRepository.findByVin(req.params.vin);
telematicsService.sendUnlockCommand(vehicle.deviceId);
res.json({ status: 'unlocked' });
});
// Corregido: compara el dueño real contra el usuario autenticado
app.get('/v1/vehicles/:vin/unlock', authenticate, (req, res) => {
const vehicle = vehicleRepository.findByVin(req.params.vin);
if (!vehicle || vehicle.ownerId !== req.user.id) {
return res.status(403).json({ error: 'forbidden' });
}
telematicsService.sendUnlockCommand(vehicle.deviceId);
res.json({ status: 'unlocked' });
});Ese chequeo, un simple if comparando dos IDs, es toda la diferencia entre una API segura y una que expone cada vehículo registrado. La limitación real es que agregarlo endpoint por endpoint, a mano, en una plataforma con cientos de rutas, es exactamente el tipo de tarea donde algo se olvida; por eso conviene centralizar la verificación de propiedad en un middleware o en una capa de autorización compartida, en vez de repetirla copiada en cada handler.
Checklist para sistemas IoT y conectados
- Propiedad explícita: cada endpoint que recibe un ID de recurso compara ese ID contra el usuario autenticado, no solo contra la existencia de un token.
- Inventario de subdominios: herramientas internas (admin, staging, QA) no deberían quedar accesibles en el internet público ni depender de "nadie las va a encontrar".
- Secretos fuera del cliente: ninguna API key de uso privilegiado debería viajar embebida en un bundle de JavaScript o en un APK descompilable.
- Pruebas cruzadas entre cuentas: el pipeline de QA debería incluir, por defecto, pedir recursos de la cuenta A usando el token de la cuenta B.
- Logs de acceso por recurso: registrar qué cuenta pidió qué VIN o qué device ID permite detectar enumeración masiva antes de que escale.
Conclusión
La autorización a nivel de objeto no es un concepto exclusivo de autos conectados: aplica a cualquier sistema IoT donde un ID identifica un dispositivo físico (una cerradura inteligente, una cámara, un panel solar). El patrón de auditoría es siempre el mismo: autenticate como alguien, pedí el recurso de otro alguien, y fijate qué responde la API.
Para quien construye estas plataformas, la lección es que la seguridad de un vehículo conectado depende tanto del backend como del hardware. Un auto puede tener cifrado perfecto en su módulo de comunicación y seguir siendo vulnerable si la API que lo controla nunca verificó de quién era.
📖 Versión extendida con más detalle: https://elsolitario.org/2026/11/09/autorizacion-a-nivel-de-objeto-la-falla-que-desbloquea-autos/?utm_source=telegraph&utm_medium=instant_view&utm_campaign=programacion