Recorre el OWASP Top 10 desde la perspectiva de un ingeniero backend — ¿cuáles ves realmente en revisiones de código reales?
El OWASP Top 10 no es una lista de cumplimiento para hojear una vez — es un ranking de los errores que aparecen una y otra vez en pull requests reales.
APRENDE HACIENDOPon a prueba tu intuición3 pasos
Recorre el OWASP Top 10 desde la perspectiva de un ingeniero backend — ¿cuáles ves realmente en revisiones de código reales?
Usa los ejemplos y la explicación de la lección para comprobar tu idea.
Reflexión personal. No se envía a ningún servicio de IA.#Qué es realmente esta lista
El OWASP Top 10 es un ranking actualizado periódicamente (la edición vigente es la de 2021) de los riesgos de seguridad más críticos en aplicaciones web, compilado a partir de datos reales de vulnerabilidades enviados por firmas de seguridad más una encuesta a la industria. No es una especificación, no es una lista de tareas que se puede "completar", y no reemplaza el modelado de amenazas de tu sistema específico — es una herramienta de priorización. Si solo tienes tiempo para corregir diez categorías de errores antes de que tu aplicación salga a producción, ahí es donde los datos dicen que hay que mirar primero.
Para un ingeniero backend sentado en una revisión de código, la mayoría de estas categorías no son abstractas — se mapean directamente a patrones específicos que reconocerás en el momento en que los veas.
#A01: Control de acceso roto (Broken Access Control)
El hallazgo más común de todos, y rara vez es sutil en el código — es un endpoint que verifica autenticación ("¿hay una sesión válida?") pero no autorización ("¿este usuario específico es dueño de este recurso específico?"). El ejemplo de manual: GET /api/invoices/:id que carga cualquier id de factura que venga en la URL y lo devuelve, sin verificar que la factura pertenezca al usuario que hace la solicitud. Cambias el id en la URL, lees la factura de otra persona. Esta clase a menudo se llama Referencia Directa a Objeto Insegura (IDOR), y sobrevive revisiones de código constantemente porque el código "se ve" correcto — la query funciona, la respuesta está bien formada, y nadie nota el filtro de propiedad que falta en la query.
#A02: Fallas criptográficas (Cryptographic Failures)
Antes llamada "Exposición de Datos Sensibles", renombrada para apuntar a la causa raíz real. Esto es: guardar contraseñas con hashes rápidos (MD5, SHA-256 sin salt ni factor de trabajo) en lugar de un algoritmo diseñado para ese propósito (bcrypt, Argon2, scrypt); transmitir datos sensibles por HTTP plano; usar un esquema de cifrado casero; o dejar una clave de cifrado escrita en el código fuente. La versión que ves constantemente en el mundo real es una clave secreta "temporal" por defecto que llegó a producción porque nadie configuró la variable de entorno.
#A03: Inyección (Injection)
La inyección SQL es la famosa, pero la categoría cubre cualquier intérprete alimentado con entrada sin sanitizar — inyección NoSQL (una query de MongoDB construida a partir de un cuerpo JSON crudo sin validación de tipos, dejando que un payload basado en operadores evada una verificación de contraseña), inyección de comandos de sistema operativo (invocar un comando de shell con un nombre de archivo crudo concatenado directamente), inyección LDAP. En revisión de código real esto aparece como concatenación de strings para construir una query en vez de una query parametrizada o el query builder de un ORM — construir el string SQL literal empalmando directamente el valor crudo, en lugar de pasar ese valor como un parámetro enlazado.
#A04: Diseño inseguro (Insecure Design)
Este es arquitectónico, no una sola línea mala — un flujo de restablecimiento de contraseña sin límite de intentos en el paso de "verificar código" de modo que un código de 6 dígitos se puede forzar por fuerza bruta en minutos, o una regla de negocio ("los usuarios pueden pedir un reembolso") implementada sin verificar cuántas veces ya lo hicieron. Esto se detecta en revisión de diseño, no buscando un patrón con grep; requiere realmente modelar las amenazas de la funcionalidad.
#A05: Configuración de seguridad incorrecta (Security Misconfiguration)
El panel de administración por defecto que quedó habilitado en producción, trazas de pila detalladas devueltas al cliente en un error 500 (regalándole al atacante la versión de tu framework y rutas de archivos gratis), un bucket de almacenamiento que quedó legible por cualquiera, CORS configurado para permitir cualquier origen junto con solicitudes con credenciales (una combinación que los navegadores deberían rechazar, pero que algunos servidores mal configurados aún emiten).
#A06: Componentes vulnerables y desactualizados (Vulnerable and Outdated Components)
Heredas esta categoría automáticamente en el momento en que instalas un paquete. Una dependencia transitiva tres niveles abajo con un CVE conocido, sin tocar porque nadie corre una auditoría de dependencias ni tiene escaneo automatizado en el CI. El modo de falla real casi nunca es "elegimos una mala librería" — es "elegimos una librería perfectamente buena hace dos años y nunca la actualizamos".
#A07: Fallas de identificación y autenticación (Identification and Authentication Failures)
Tokens de sesión que no rotan después del login (fijación de sesión), sin bloqueo de cuenta ni límite de intentos en el login, tokens de "recordarme" que nunca expiran, tokens de restablecimiento de contraseña que no son de un solo uso o que no expiran rápido. Esto se superpone con A02 pero trata específicamente del flujo de autenticación, no solo de las primitivas criptográficas debajo de él.
#A08: Fallas de integridad de software y datos (Software and Data Integrity Failures)
Confiar en datos o código sin verificar su integridad — deserializar datos no confiables con un formato que puede ejecutar código arbitrario al cargarse, un mecanismo de auto-actualización que descarga un binario por HTTP plano sin verificación de firma, o un pipeline de CI/CD que descarga una dependencia de build desde un tag mutable y sin fijar.
#A09: Fallas de registro y monitoreo de seguridad (Security Logging and Monitoring Failures)
No es algo que un atacante explote directamente, sino la razón por la que una brecha que empezó pequeña pasa meses sin detectarse — sin registro de fallos de autenticación, sin alertas ante un pico de 403 desde una sola IP, logs que se escriben pero que nadie jamás revisa ni sobre los cuales hay alertas configuradas. En revisión de código real, esto es la ausencia de una llamada de log de advertencia ante un intento de login fallido, mucho más fácil de pasar por alto que un bug que sí está presente.
#A10: Falsificación de solicitudes del lado del servidor (SSRF)
La entrada más nueva, y cada vez más común a medida que las aplicaciones agregan funciones de "trae esta URL por mí" — validadores de webhooks, proxy de imágenes por URL, generación de PDF a partir de un enlace suministrado por el usuario. Si el servidor descarga una URL que el usuario provee sin restringirla, un atacante la apunta al endpoint interno de metadatos de un proveedor cloud o a un servicio administrativo de solo acceso interno, y lee la respuesta a través de tu aplicación.
#Lo que realmente aparece en la práctica
Si revisas pull requests de backend día a día, el ranking honesto por frecuencia difiere del ranking oficial basado en datos de incidentes: A01 (control de acceso roto) y A03 (inyección, sobre todo la variante NoSQL/bypass de ORM ahora que la concatenación de SQL crudo es más rara) son lo que marcarás semanalmente. A05 (configuración incorrecta) aparece constantemente en revisión de infraestructura como código más que en código de aplicación. A06 (dependencias vulnerables) la detectan herramientas más a menudo que un revisor humano, que es exactamente el punto de automatizarlo. A09 (fallas de registro) es la que la mayoría de los revisores sistemáticamente olvidan verificar, precisamente porque es una ausencia, no una presencia.