En la lección anterior situamos el diseño como la fase de mayor retorno del S-SDLC, y su actividad estrella como el modelado de amenazas. Ya lo anticipamos en la lección 03-05 (Diseño Inseguro), donde dijimos que un fallo de arquitectura no se corrige con un parche y que la forma de anticiparlo tenía nombre propio, cuyo desarrollo dejábamos para aquí. Ha llegado el momento. El modelado de amenazas es el ejercicio estructurado de imaginar, antes de construir, cómo un adversario intentaría abusar del sistema, para decidir qué defensas incorporar por diseño. Es la disciplina que responde a la pregunta que un pentest solo responde tarde y caro: ¿qué puede salir mal? En esta lección construimos un threat model completo del checkout de BazarNube.
Contenido
- Qué es el modelado de amenazas y cuándo hacerlo
- Las cuatro preguntas de Shostack
- Diagramas de flujo de datos (DFD) y límites de confianza
- STRIDE: un lenguaje de categorías de amenaza
- Priorización de riesgos (DREAD y alternativas)
- Herramientas: Threat Dragon y pytm
- Threat model del checkout de BazarNube
- Errores comunes y consejos
- Ejercicios
- Conclusión
Qué es el modelado de amenazas y cuándo hacerlo
Modelar amenazas es analizar un diseño buscando de forma sistemática sus puntos débiles y las contramedidas apropiadas. No requiere que el sistema esté construido: se hace sobre diagramas y decisiones, que es precisamente su ventaja. Es un ejercicio de equipo, no un informe que redacta un experto en solitario; el valor está tanto en el documento resultante como en la conversación que lo produce.
¿Cuándo hacerlo?
- Al diseñar una funcionalidad nueva con datos sensibles o dinero de por medio.
- Ante un cambio de arquitectura relevante (nuevo servicio, nueva integración externa, nuevo almacén de datos).
- De forma periódica sobre componentes críticos, porque el sistema y las amenazas evolucionan.
- No es realista modelar cada commit: se reserva para lo que importa, guiado por la clasificación de datos que hicimos en la fase de requisitos.
Las cuatro preguntas de Shostack
Adam Shostack popularizó un marco de cuatro preguntas que estructura cualquier sesión de modelado. OWASP lo adopta como columna vertebral del proceso.
| # | Pregunta | Qué produce |
|---|---|---|
| 1 | ¿Qué estamos construyendo? | Un DFD con sus límites de confianza |
| 2 | ¿Qué puede salir mal? | Lista de amenazas (con STRIDE) |
| 3 | ¿Qué vamos a hacer al respecto? | Mitigaciones y controles |
| 4 | ¿Lo hicimos bien? | Verificación y revisión |
La cuarta pregunta cierra el bucle: un threat model no es un artefacto muerto, se revisa cuando el diseño cambia. Nótese el paralelismo con el S-SDLC: la pregunta 3 alimenta requisitos ASVS y la pregunta 4 se apoya en verificación (por ejemplo, ZAP comprobando que una mitigación funciona).
Diagramas de flujo de datos (DFD) y límites de confianza
Para responder "¿qué construimos?" se dibuja un Diagrama de Flujo de Datos (Data Flow Diagram). Un DFD usa un vocabulario deliberadamente pequeño:
- Entidad externa (rectángulo): actor fuera de nuestro control (usuario, pasarela de pago).
- Proceso (círculo): código que transforma datos (una API, un servicio).
- Almacén de datos (dos líneas paralelas): base de datos, caché, cola.
- Flujo de datos (flecha): el movimiento de datos entre los anteriores.
- Límite de confianza (línea discontinua): la frontera donde cambia el nivel de confianza; cruzarla es donde nacen la mayoría de las amenazas.
Los límites de confianza son el concepto clave. Cada vez que un dato cruza uno —de Internet a nuestra API, de nuestra API a la base de datos, de nuestro backend a un servicio de terceros— hay una oportunidad para el atacante y una necesidad de validar, autenticar o cifrar. Modelar bien consiste, en buena medida, en enfocar la atención en esos cruces.
STRIDE: un lenguaje de categorías de amenaza
Responder "¿qué puede salir mal?" a mano lleva a olvidos. STRIDE, creado en Microsoft, es una mnemónica que fuerza a considerar seis categorías de amenaza para cada elemento del DFD. Cada categoría es la negación de una propiedad de seguridad deseable.
| Letra | Amenaza | Propiedad violada | Ejemplo | Riesgo Top Ten relacionado |
|---|---|---|---|---|
| S | Spoofing (suplantación) | Autenticación | Hacerse pasar por otro usuario | A07 Fallos de Identificación y Autenticación |
| T | Tampering (manipulación) | Integridad | Alterar el precio en la petición | A08 Fallos de Integridad; A03 Inyección |
| R | Repudiation (repudio) | No repudio | Negar haber hecho un pedido | A09 Fallos de Registro y Monitorización |
| I | Information disclosure | Confidencialidad | Ver datos de tarjeta de otro | A01 Control de Acceso; A02 Fallos Criptográficos |
| D | Denial of service | Disponibilidad | Saturar el checkout | A05 Configuración incorrecta (límites) |
| E | Elevation of privilege | Autorización | Usuario normal actúa como admin | A01 Control de Acceso Roto |
Una técnica práctica es STRIDE-per-element: recorrer cada proceso, almacén y flujo del DFD y preguntarse qué letras de STRIDE aplican. No todas aplican a todos los elementos, y eso está bien; el valor es la cobertura sistemática.
Priorización de riesgos (DREAD y alternativas)
No todas las amenazas merecen la misma atención. Hace falta priorizar para invertir el esfuerzo donde importa. DREAD es un modelo clásico que puntúa cada amenaza en cinco ejes (típicamente 1-3 o 1-10):
- Damage — daño potencial.
- Reproducibility — facilidad de reproducir el ataque.
- Exploitability — esfuerzo para explotarlo.
- Affected users — cuántos usuarios afecta.
- Discoverability — facilidad de descubrir la vulnerabilidad.
Se suman los ejes y se ordena. DREAD es simple pero subjetivo (dos personas puntúan distinto), por lo que muchos equipos prefieren alternativas:
| Método | Ventaja | Inconveniente |
|---|---|---|
| DREAD | Rápido, intuitivo | Subjetivo, poco reproducible |
| Matriz probabilidad x impacto | Alineada con gestión de riesgos general | Requiere calibrar escalas |
| CVSS | Estándar de la industria | Pensado para vulnerabilidades, no amenazas de diseño |
| OWASP Risk Rating | Adaptado a apps web, factores claros | Más pasos |
Para BazarNube usaremos una simple matriz probabilidad x impacto (Alto/Medio/Bajo), suficiente para priorizar y fácil de consensuar en equipo.
Herramientas: Threat Dragon y pytm
Modelar puede hacerse en una pizarra, pero hay herramientas que ayudan a mantener el modelo vivo y versionado:
- OWASP Threat Dragon: aplicación gráfica (web y escritorio) para dibujar DFDs y anotar amenazas STRIDE. Guarda el modelo como JSON, versionable en Git junto al código. Ideal para equipos que prefieren lo visual.
- pytm: framework de threat modeling as code en Python. Se describe el sistema como objetos (procesos, almacenes, flujos, límites) en un script y la herramienta genera el DFD y un informe de amenazas. Encaja con la filosofía "todo como código" que veremos en DevSecOps.
# Esbozo minimo con pytm: el sistema se describe como codigo
from pytm import TM, Server, Datastore, Actor, Boundary, Dataflow
tm = TM("Checkout BazarNube")
internet = Boundary("Internet")
interna = Boundary("Red interna")
cliente = Actor("Cliente"); cliente.inBoundary = internet
api = Server("API Checkout (Node/Express)"); api.inBoundary = interna
db = Datastore("PostgreSQL Pedidos"); db.inBoundary = interna
pago = Dataflow(cliente, api, "Enviar datos de pago (HTTPS)")
guardar = Dataflow(api, db, "Guardar pedido")
tm.process() # genera DFD e informe de amenazasLa herramienta no sustituye el criterio: es el equipo quien decide qué amenazas son reales y qué mitigaciones aplican.
Threat model del checkout de BazarNube
Apliquemos las cuatro preguntas al flujo más sensible de BazarNube: el checkout, donde convergen datos personales, direcciones y el pago.
Pregunta 1: ¿Qué construimos? (DFD)
graph LR
Cliente[Cliente navegador React]
API[API Checkout Node/Express]
Legacy[Servicio precios Java/Spring]
DB[(PostgreSQL Pedidos)]
Pasarela[Pasarela de pago externa]
Cliente -->|1 datos pedido HTTPS| API
API -->|2 consulta precio| Legacy
API -->|3 guarda pedido| DB
API -->|4 tokeniza y cobra| Pasarela
Pasarela -->|5 webhook confirmacion| API
subgraph TB_Internet [Limite de confianza: Internet]
Cliente
end
subgraph TB_Interna [Limite de confianza: Red interna]
API
Legacy
DB
end
subgraph TB_Tercero [Limite de confianza: Tercero]
Pasarela
end
Los cruces de límite de confianza son: cliente→API (Internet a interna), API→pasarela y el webhook pasarela→API (interna a tercero). Ahí concentramos el análisis.
Pregunta 2 y 3: ¿Qué puede salir mal y qué hacemos? (STRIDE + mitigaciones)
| Elemento / flujo | STRIDE | Amenaza concreta | Prob. x Impacto | Mitigación | Control OWASP |
|---|---|---|---|---|---|
| Cliente → API | T | Manipular el precio en el JSON del pedido | Alta x Alto | El precio se recalcula en el servidor desde el catálogo; nunca se confía en el del cliente | A04 Diseño; ASVS V5 (validación) |
| Cliente → API | S | Usar la sesión/token de otro cliente | Media x Alto | Tokens de sesión robustos, rotación, MFA en cambios sensibles | A07; ASVS V2, V3 |
| API (proceso) | E | Usuario normal fuerza el pedido de otro (IDOR) | Alta x Alto | Autorización por objeto: el pedido se liga al usuario autenticado | A01; ASVS V4 |
| API → DB | I | Fuga de datos de pedidos por inyección | Media x Alto | Consultas parametrizadas; mínimo privilegio del usuario de BD | A03; ASVS V5 |
| API ↔ Pasarela | I | Exposición de datos de tarjeta | Baja x Muy alto | No almacenar PAN; tokenización en la pasarela; TLS | A02; ASVS V6, V9 |
| Webhook Pasarela → API | S/T | Webhook falsificado que confirma un pago inexistente | Media x Alto | Verificar firma HMAC del webhook; validar importe contra el pedido | A08; ASVS V10 |
| Checkout (flujo) | D | Abuso del endpoint para agotar stock o saturar | Media x Medio | Rate limiting, control de concurrencia sobre stock | A05; ASVS V11 |
| API (proceso) | R | Cliente niega haber hecho un pedido | Baja x Medio | Registro íntegro y con marca temporal de cada transacción | A09; ASVS V7 |
Obsérvese cómo cada mitigación enlaza con un control ya estudiado: el threat model no inventa defensas nuevas, sino que decide cuáles del catálogo Top Ten/ASVS aplican a este diseño. El threat model traduce riesgos genéricos en requisitos concretos y verificables. Ese es exactamente el puente hacia la fase de pruebas, donde ZAP y las pruebas manuales confirmarán que la mitigación funciona.
Pregunta 4: ¿Lo hicimos bien?
El Security Champion del equipo revisa el modelo, se registran las mitigaciones como requisitos de aceptación (ASVS) en el backlog, y se marca el modelo para revisión cuando cambie la pasarela o se añada, por ejemplo, pago aplazado. La amenaza del webhook falsificado se convierte en una historia con su prueba correspondiente.
Errores Comunes y Consejos
- Modelar el sistema perfecto, no el real. El DFD debe reflejar cómo funciona de verdad, incluidos los atajos y el servicio legacy de Java. Un modelo idealizado oculta las amenazas reales.
- Buscar la exhaustividad absoluta. Es imposible enumerar toda amenaza. Prioriza los cruces de límite de confianza y los datos sensibles; un modelo "suficientemente bueno" y revisado supera a uno perfecto que nunca se termina.
- Convertirlo en un documento muerto. Si el modelo no se revisa cuando cambia el diseño, caduca. Vincúlalo al proceso (pregunta 4) y guárdalo versionado junto al código.
- Hacerlo en solitario. El valor está en la conversación entre desarrollo, seguridad y producto. Sin el equipo, se pierde el conocimiento del sistema real.
- Consejo: empieza pequeño. Un DFD en pizarra de una hora sobre el flujo más crítico aporta más que un curso teórico. La habilidad se desarrolla modelando.
Ejercicios
Ejercicio 1. En el DFD del checkout, un desarrollador propone que el frontend envíe el precio total ya calculado "para ahorrar una consulta". Identifica la categoría STRIDE del riesgo y la mitigación correcta.
Ejercicio 2. Clasifica cada amenaza con la letra STRIDE adecuada: (a) un atacante repite un webhook de pago capturado, (b) un usuario cambia el order_id de la URL y ve el pedido de otro, (c) el log no registra quién canceló un pedido.
Ejercicio 3. BazarNube va a añadir "iniciar sesión con Google". Dibuja mentalmente el nuevo flujo e indica un nuevo límite de confianza y una amenaza STRIDE que aparece con esta integración.
Soluciones
Solución 1. Es Tampering (manipulación de integridad): confiar en un precio enviado por el cliente permite alterarlo en tránsito o desde el navegador y comprar por menos. La mitigación es no confiar nunca en datos del cliente para decisiones de dinero: el servidor recalcula el precio desde el catálogo autorizado. Relaciona con A04 (Diseño Inseguro) y ASVS V5 (validación).
Solución 2.
- (a) Tampering y/o Spoofing (webhook de replay/falsificado); se mitiga con firma HMAC y control anti-replay (nonce/timestamp).
- (b) Elevation of privilege / control de acceso roto (IDOR); autorización por objeto.
- (c) Repudiation; registro íntegro con identidad y marca temporal.
Solución 3. Aparece un nuevo límite de confianza con el proveedor de identidad externo (Google) y el flujo OAuth/OIDC que cruza a un tercero. Una amenaza típica es Spoofing: aceptar un token de identidad no validado correctamente (firma, audiencia, emisor, expiración) permitiría suplantar a un usuario. Se mitiga validando el token según el estándar OIDC y ligando la cuenta local de forma segura. Relaciona con A07 y ASVS V2/V3.
Conclusión
El modelado de amenazas es la práctica que da contenido a la fase de diseño del S-SDLC: con un DFD y sus límites de confianza respondemos "qué construimos", con STRIDE "qué puede salir mal", con mitigaciones enlazadas al Top Ten y ASVS "qué hacemos", y con la revisión "lo hicimos bien". En BazarNube hemos convertido un flujo de checkout en una lista priorizada de requisitos verificables. Pero un buen diseño solo se sostiene si el resto del proceso lo respeta de forma automática y continua. En la siguiente lección, 07-03, llevamos estas mitigaciones al terreno de la automatización: cómo DevSecOps convierte estos controles en comprobaciones que el pipeline ejecuta en cada cambio.
Curso de OWASP: Directrices y Estándares para la Seguridad en Aplicaciones Web
Módulo 1: Introducción a OWASP
Módulo 2: Principales Proyectos de OWASP
- OWASP Top Ten
- OWASP ASVS (Application Security Verification Standard)
- OWASP SAMM (Software Assurance Maturity Model)
- OWASP ZAP (Zed Attack Proxy)
- Otros Proyectos Clave: WSTG, Cheat Sheets y Dependency-Check
Módulo 3: OWASP Top Ten 2021 en Profundidad
- A01:2021 – Pérdida de Control de Acceso
- A02:2021 – Fallos Criptográficos y Exposición de Datos Sensibles
- A03:2021 – Inyección
- Cross-Site Scripting (XSS) en Profundidad
- A04:2021 – Diseño Inseguro
- A05:2021 – Configuración de Seguridad Incorrecta
- Entidades Externas XML (XXE)
- A06:2021 – Componentes Vulnerables y Desactualizados
- A07:2021 – Fallos de Identificación y Autenticación
- A08:2021 – Fallos de Integridad de Software y Datos (Deserialización Insegura)
- A09:2021 – Fallos de Registro y Monitorización
- A10:2021 – Server-Side Request Forgery (SSRF)
Módulo 4: OWASP ASVS (Application Security Verification Standard)
- Introducción a ASVS
- Niveles de Verificación
- Requisitos de Seguridad
- Implementación de ASVS en Proyectos
Módulo 5: OWASP SAMM (Software Assurance Maturity Model)
Módulo 6: OWASP ZAP (Zed Attack Proxy)
- Introducción a ZAP
- Instalación y Configuración
- Escaneo de Vulnerabilidades
- Automatización de Pruebas de Seguridad
Módulo 7: Buenas Prácticas y Recomendaciones
- Ciclo de Vida de Desarrollo Seguro (SDLC)
- Modelado de Amenazas (Threat Modeling)
- Integración de Seguridad en DevOps (DevSecOps)
- Capacitación y Concienciación en Seguridad
- Herramientas y Recursos Adicionales
Módulo 8: Ejercicios Prácticos y Casos de Estudio
- Ejercicio 1: Identificación de Vulnerabilidades
- Ejercicio 2: Implementación de Controles de Seguridad
- Caso de Estudio 1: Análisis de un Incidente de Seguridad
- Caso de Estudio 2: Mejora de la Seguridad en una Aplicación Web
