STRIDE
Las seis categorías de amenaza de STRIDE, qué propiedad de seguridad viola cada una y cómo aplicarlas de forma sistemática a cada elemento de un diagrama de flujo de datos.
La pregunta “¿qué puede salir mal?” delante de un diagrama en blanco suele producir dos cosas: silencio o una lista de vulnerabilidades de moda (“¿y la inyección SQL?”). STRIDESTRIDEMnemotecnia de Microsoft (1999) con seis categorías de amenaza; cada una viola una propiedad de seguridad distinta. resuelve ese bloqueo con seis preguntas concretas que se hacen a cada elemento del sistema. No garantiza encontrarlo todo, pero hace que el análisis sea sistemático y repetible: dos equipos distintos que aplican STRIDE al mismo DFD llegan a listas parecidas.
De dónde viene#
Loren Kohnfelder y Praerit Garg lo propusieron en Microsoft en 1999, en un documento interno titulado The Threats to Our Products. El nombre es un acrónimo: cada letra es una categoría de amenaza, y cada categoría es lo contrario de una propiedad de seguridad que el sistema debería garantizar.
Las seis categorías#
| Letra | Amenaza | Propiedad que viola | Pregunta guía |
|---|---|---|---|
| S | Spoofing (suplantación) | Autenticación | ¿Puede alguien hacerse pasar por otro usuario, servicio o componente? |
| T | Tampering (manipulación) | Integridad | ¿Puede alguien modificar datos en tránsito, en reposo o en memoria? |
| R | Repudiation (repudio) | No repudioNo repudioGarantía de que alguien no puede negar de forma creíble haber realizado una acción, porque existe una evidencia fiable de ella. | ¿Puede alguien negar haber hecho algo sin que podamos demostrarlo? |
| I | Information disclosure (revelación) | Confidencialidad | ¿Puede alguien ver datos que no debería? |
| D | Denial of service (denegación de servicio) | Disponibilidad | ¿Puede alguien impedir que el sistema funcione para los usuarios legítimos? |
| E | Elevation of privilege (elevación de privilegios) | Autorización | ¿Puede alguien hacer cosas para las que no tiene permiso? |
Tres de las propiedades (confidencialidad, integridad y disponibilidad) son la tríada CIA. STRIDE añade autenticación, no repudio y autorización, que son las que suelen fallar en aplicaciones web y en cloud.
Paso 1 de 7S · Spoofing
Suplantación: alguien se hace pasar por un paciente con una contraseña filtrada. Viola la autenticación; se mitiga con un proveedor de identidad y MFA.
STRIDE en Citas#
Aplicado al sistema de referencia, cada categoría se traduce en amenazas concretas y en las mitigaciones que las frenan. Las mitigaciones se describen por lo que hacen; entre paréntesis va el nombre que reciben en la nube de referencia (AWS):
| Amenaza en Citas | Mitigación | |
|---|---|---|
| S | Un atacante inicia sesión con la contraseña filtrada de un paciente | Proveedor de identidad gestionado con MFA (obligatoria para el personal), detección de credenciales comprometidas, roles de identidad en los contenedores en vez de claves estáticas |
| T | Se modifica el clinic_id de una reserva o un documento ya subido al almacén de objetos |
TLS en todos los flujos, validación en servidor, tokens de sesión firmados, versionado del almacén de objetos |
| R | Una recepcionista niega haber cancelado una cita | Log de auditoría de aplicación con la identidad del token, registros de auditoría firmados del proveedor (ejemplo: CloudTrail) para acciones sobre la infraestructura, logs en una cuenta de archivo aislada con almacenamiento inmutable (WORM) |
| I | Un IDOR permite leer citas de otra clínica; un snapshot de la base de datos se comparte por error | Autorización por tenant en cada consulta (o Row-Level Security de PostgreSQL), cifrado con clave gestionada, bloqueo del acceso público al almacenamiento, no registrar PII en los logs |
| D | Una avalancha de reservas falsas agota las conexiones de la base de datos | Límites de tasa en el borde (WAF rate-based), protección DDoS, autoescalado de los contenedores, pool de conexiones a la base de datos, procesamiento asíncrono con colas de mensajes |
| E | El paciente envía role: "admin" y la API lo guarda (mass assignment) |
RBAC en el servidor, lista blanca de campos, roles de identidad de mínimo privilegio, políticas de control a nivel de organización |
La amenaza E es de las más habituales en APIs. El fallo está en confiar en el cuerpo de la petición tal como llega:
Vulnerable
Seguro
app.patch('/api/usuarios/:id', auth, async (req, res) => { const usuario = await db.usuarios.findById(req.params.id); Object.assign(usuario, req.body); // incluye "role" si el cliente lo envía await usuario.save(); res.json(usuario);});const Perfil = z .object({ nombre: z.string().max(80), telefono: z.string().regex(/^\+?[0-9 ]{7,15}$/), }) .strict(); // rechaza cualquier campo no declarado, como "role"
app.patch('/api/usuarios/:id', auth, async (req, res) => { if (req.params.id !== req.user.id) return res.sendStatus(403); const cambios = Perfil.parse(req.body); await db.usuarios.update(req.user.id, cambios); res.sendStatus(204);});La versión segura corrige dos amenazas a la vez: la E (no se puede tocar role) y una I/T por IDOR (no se puede editar el perfil de otro usuario cambiando el :id).
STRIDE por elemento#
No todas las letras aplican a todos los elementos del DFD. Microsoft popularizó esta tabla, que ahorra mucho tiempo:
| Elemento | S | T | R | I | D | E |
|---|---|---|---|---|---|---|
| Entidad externa | ✓ | ✓ | ||||
| Proceso | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
| Almacén de datos | ✓ | ✓* | ✓ | ✓ | ||
| Flujo de datos | ✓ | ✓ | ✓ |
* El repudio aplica a un almacén cuando ese almacén es un registro de auditoría: si alguien puede borrarlo o alterarlo, nadie puede demostrar lo que pasó.
La lógica es intuitiva: una entidad externa puede ser suplantada o negar sus actos, pero no “manipularla” tú; un flujo puede ser interceptado, alterado o cortado, pero no “eleva privilegios” por sí mismo; un proceso, que ejecuta código, puede sufrirlo todo.
-
Recorre el DFD elemento a elemento
Empieza por los procesos y flujos que cruzan límites de confianza.
-
Para cada elemento, pregunta solo las letras que aplican
Un flujo: ¿se puede alterar (T), leer (I) o cortar (D)?
-
Redacta cada amenaza de forma concreta
Quién, en qué condiciones, qué hace y qué consigue (ver abajo).
-
No discutas la categoría, discute la amenaza
Si dudas entre I y E, elige una y sigue. La etiqueta sirve para no olvidarse de nada, no es el resultado.
STRIDE por interacción#
Una variante más fina analiza interacciones: tuplas de origen, destino y flujo (por ejemplo, “Paciente → Edge: reserva”). En lugar de preguntar por cada elemento aislado, se pregunta qué puede salir mal en esa interacción concreta, sobre todo cuando cruza un límite de confianza. Es el enfoque que usa Microsoft Threat Modeling Tool para generar amenazas automáticamente a partir del diagrama. Produce menos duplicados en sistemas grandes, a cambio de más trabajo inicial.
Cómo redactar una amenaza#
“Inyección SQL” no es una amenaza, es una categoría de vulnerabilidad. Una amenaza útil dice quién puede hacer qué, en qué condiciones y con qué impacto. Una estructura que funciona bien (inspirada en la gramática de amenazas de threat-composer):
[Fuente de la amenaza] [con estas precondiciones] puede [acción], lo que provoca [impacto], afectando a la [propiedad] de [activos].
Aplicado a Citas:
Un atacante externo que dispone de credenciales filtradas de un paciente puede iniciar sesión como ese paciente, lo que le permite ver y cancelar sus citas, afectando a la confidencialidad e integridad de los datos de citas del paciente.
Redactada así, la amenaza ya sugiere las mitigaciones (MFA, detección de credenciales comprometidas, alertas de inicio de sesión) y se puede priorizar con criterio.
Para las amenazas de repudio, la mitigación casi siempre es un registro que nadie pueda alterar. Los registros de auditoría del proveedor de nube (ejemplo: CloudTrail) cubren las acciones sobre la infraestructura, pero “cancelar una cita” es una acción de tu aplicación, así que necesitas tu propio log de auditoría con la identidad del token:
{ "timestamp": "2026-10-11T09:42:17Z", "actor": { "sub": "c0a8f2e4-91b7-4d2a-9f60-1e2b3c4d5e6f", "rol": "recepcionista", "clinica": "clinica-12" }, "accion": "cita.cancelar", "recurso": "cita/8f31", "origen": { "ip": "203.0.113.24" }, "resultado": "ok", "request_id": "a1f3c9e2-7b44-4c1d-8e0f-5d6a7b8c9d0e"}Y para que ni un administrador pueda borrarlo, se guarda en un almacén de objetos con retención inmutable (WORM) en modo compliance: durante el periodo de retención (por ejemplo, 365 días) nadie —ni siquiera la cuenta raíz— puede borrar ni sobrescribir los objetos. Casi todas las nubes ofrecen esta garantía bajo otro nombre:
| Control | AWS | Azure | Google Cloud |
|---|---|---|---|
| Almacenamiento inmutable WORM | S3 Object Lock | Blob immutable storage | Bucket Lock |
Tu turno
Modela una app de 3 capas que ya hayas construido
Toma el DFD de tu app (si aún no lo tienes, sigue el ejercicio de flujos de datos) y aplica STRIDE por elemento a los flujos que cruzan límites de confianza.
- ¿Qué letra te ha costado más encontrar? Suele ser la R: ¿tu app registra quién hizo cada acción sensible?
- ¿Alguna amenaza tiene ya mitigación en tu infraestructura actual? ¿Cuál no?
- Redacta al menos tres amenazas completas con la estructura fuente, precondición, acción, impacto y activo.
| Elemento / flujo | Letra | Amenaza | Mitigación existente | Pendiente |
|---|---|---|---|---|
| … | … | … | … | … |
El caso práctico de app de 3 capas muestra la tabla completa para Citas.
Reto
Un usuario cambia ?clinica=12 por ?clinica=13 en la URL y ve las citas de otra clínica. ¿Qué categoría STRIDE es?
▸Mostrar solución
Principalmente I (revelación de información): accede a datos que no debería ver. Si además pudiera modificar o cancelar esas citas, también sería E (actúa con permisos que no tiene) y T sobre los datos. La causa raíz es un fallo de autorización (IDOR / broken access control), y la mitigación es comprobar en el servidor que la clínica pedida es la del usuario autenticado.
Reto
¿Por qué la tabla de STRIDE por elemento no marca Spoofing para los almacenes de datos?
▸Mostrar solución
Porque un almacén no inicia acciones ni se autentica ante nadie: son los procesos los que acceden a él. La suplantación ocurre en quien accede (un proceso que se hace pasar por la API para leer de la base de datos), así que se analiza en ese proceso o en el flujo, no en el almacén.
En resumen#
- STRIDE son seis categorías de amenaza: Spoofing, Tampering, Repudiation, Information disclosure, Denial of service, Elevation of privilege.
- Cada una viola una propiedad: autenticación, integridad, no repudio, confidencialidad, disponibilidad y autorización.
- STRIDE por elemento limita las preguntas según el tipo de elemento del DFD; por interacción analiza origen, destino y flujo.
- Empieza por los flujos que cruzan límites de confianza.
- Una amenaza útil dice quién, en qué condiciones, qué hace y con qué impacto.
- El repudio necesita logs de auditoría propios e inmutables; los registros del proveedor de nube (ejemplo: CloudTrail) solo cubren las acciones sobre la infraestructura.
Referencias#
- Microsoft: Threat Modeling Tool, categorías de amenazas
- Adam Shostack, Threat Modeling: Designing for Security (Wiley, 2014), capítulo 3
- OWASP Threat Modeling Cheat Sheet
- threat-composer (AWS Labs)
- Amazon S3 Object Lock
- AWS WAF: reglas rate-based
- OWASP API Security Top 10: Broken Object Property Level Authorization