Flujos de datos y límites de confianza
Cómo dibujar un diagrama de flujo de datos (DFD) útil para seguridad y marcar dónde cambia la confianza, que es donde se concentran las amenazas.
No puedes encontrar amenazas en un sistema que no ves. El diagrama de arquitectura habitual, con logos del proveedor de nube y flechas que van “más o menos” hacia la base de datos, sirve para explicar el despliegue, pero responde mal a la pregunta que importa en seguridad: ¿qué datos se mueven, entre quién y a través de qué fronteras? El diagrama de flujo de datosDiagrama de flujo de datosDiagrama con entidades externas, procesos, almacenes y flujos de datos con dirección; es el modelo habitual sobre el que se buscan amenazas. (DFD) responde exactamente eso, y es el modelo sobre el que se aplica STRIDE.
Los elementos de un DFD#
Un DFD tiene solo cuatro tipos de elementos y un quinto concepto que los atraviesa:
| Elemento | Notación | Qué representa | Ejemplo en Citas |
|---|---|---|---|
| Entidad externa | Rectángulo | Personas o sistemas que interactúan con el tuyo pero no controlas | Paciente, recepcionista, proveedor de SMS |
| Proceso | Círculo | Código que recibe, transforma o envía datos | API en contenedores gestionados, worker de recordatorios |
| Almacén de datos | Dos líneas paralelas | Datos en reposo | Base de datos gestionada (PostgreSQL), almacén de objetos citas-adjuntos, cola de mensajes |
| Flujo de datos | Flecha con nombre | Datos en movimiento, con dirección | “Reserva (HTTPS + JWT)”, “SQL (TLS)” |
| Límite de confianza | Línea o caja discontinua | Dónde cambia el nivel de confianza | Internet ↔ borde, red privada ↔ subred de datos |
Dos detalles importan más de lo que parece. Los flujos tienen dirección porque las amenazas dependen de quién envía y quién recibe. Y los almacenes no se hablan entre sí: siempre hay un proceso en medio, aunque sea un servicio gestionado (la replicación del almacén de objetos es un proceso del proveedor).
Paso 1 de 6Entidades externas
Empezamos por quién interactúa con el sistema pero queda fuera de nuestro control: pacientes, personal de la clínica y el proveedor de SMS.
Límites de confianza#
Un límite de confianzaLímite de confianzaFrontera donde cambia el nivel de confianza o de privilegio; todo lo que la cruza debe autenticarse, autorizarse, validarse y, normalmente, cifrarse. es una frontera donde cambia el nivel de confianza o de privilegio entre lo que hay a cada lado. Cuando un dato o una orden cruza de un lado menos confiable a otro más confiable, el receptor no puede asumir nada: tiene que autenticar al emisor, autorizar la acción, validar la entrada y, normalmente, cifrar el canal.
En una arquitectura de nube típica aparecen siempre los mismos límites:
- Internet → borde: cualquier cliente llega al CDN o al balanceador. Nada de lo que envía es de fiar.
- Borde → red privada: el tráfico ya ha pasado por WAF y TLS, pero el contenido sigue viniendo del usuario.
- Aplicación → datos: la API habla con la base de datos gestionada y el almacén de objetos usando credenciales con más privilegio que el usuario final.
- Cuenta → cuenta: roles que se asumen entre cuentas (por ejemplo, prod escribiendo en un archivo de logs centralizado).
- Tu sistema → terceros: proveedores de SMS o email, APIs de pago, webhooks entrantes.
- CI/CD → producción: el pipeline que despliega tiene, por definición, poder sobre prod.
- Humanos con privilegios → consola: administradores, accesos de emergencia, sesiones de acceso remoto.
Niveles de detalle#
Los DFD se dibujan por niveles, como un mapa con zoom:
- Diagrama de contexto (nivel 0): el sistema entero como un único proceso, rodeado de sus entidades externas. Sirve para acordar el alcance.
- Nivel 1: los procesos y almacenes principales. Es el nivel donde se hace casi todo el modelado de amenazas.
- Nivel 2 o más: el detalle de un proceso concreto (por ejemplo, el flujo de autenticación con un proveedor de identidad gestionado). Solo cuando un área lo merece.
Si el diagrama no cabe en una pantalla, probablemente estás mezclando niveles.
El DFD de Citas#
Elementos del nivel 1:
| Tipo | Elemento | Zona de confianza |
|---|---|---|
| Entidad externa | Paciente, recepcionista | Internet |
| Entidad externa | Proveedor SMS (vía mensajería gestionada) | Tercero |
| Proceso | Borde: CDN + WAF + balanceador | Borde |
| Proceso | API Node.js (contenedores gestionados) | Red privada |
| Proceso | Worker de recordatorios | Red privada |
| Almacén | Base de datos gestionada (PostgreSQL, citas, PII) | Datos (subred aislada) |
| Almacén | Almacén de objetos citas-adjuntos (documentos) |
Datos |
Y lo más importante, los flujos que cruzan un límite, con lo que exige cada uno:
| Flujo | Límite que cruza | Qué hay que garantizar |
|---|---|---|
| Paciente → Borde: reserva | Internet → borde | TLS, WAF, autenticación con JWT del proveedor de identidad |
| Recepcionista → Borde: agenda | Internet → borde | Igual que el anterior, más MFA para personal |
| Borde → API: petición con JWT | Borde → red priv. | Validar firma y expiración del JWT, validar la entrada |
| API → BD: consulta SQL | Red priv. → datos | Credenciales de un gestor de secretos, TLS, filtro por clínica |
| API → objetos: subida de documento | Red priv. → datos | Rol con permisos solo sobre el prefijo, cifrado con clave gestionada |
| Worker → proveedor SMS | Red priv. → tercero | Mínimos datos posibles en el mensaje (sin notas clínicas) |
| CI/CD → cuenta prod | CI/CD → prod | Identidad federada (OIDC) restringida a repositorio y rama |
Codificar los límites#
Un límite dibujado en el diagrama tiene que existir también en la infraestructura. El límite red privada → datos, por ejemplo, se materializa en un grupo de seguridad (o lista de control de red) que solo acepta conexiones desde la API. Así se ve con Terraform sobre AWS:
resource "aws_security_group" "rds" { name = "citas-rds" vpc_id = aws_vpc.main.id
ingress { description = "PostgreSQL solo desde la API" security_groups = [aws_security_group.api.id] from_port = 5432 to_port = 5432 protocol = "tcp" }}Y el límite CI/CD → prod, en la política de confianza de la identidad federada que asume el pipeline. En el ejemplo en AWS de abajo, sin la condición sub, cualquier repositorio de GitHub podría intentar asumir el rol.
Vulnerable
Seguro
{ "Effect": "Allow", "Principal": { "Federated": "arn:aws:iam::111122223333:oidc-provider/token.actions.githubusercontent.com" }, "Action": "sts:AssumeRoleWithWebIdentity", "Condition": { "StringEquals": { "token.actions.githubusercontent.com:aud": "sts.amazonaws.com" } }}{ "Effect": "Allow", "Principal": { "Federated": "arn:aws:iam::111122223333:oidc-provider/token.actions.githubusercontent.com" }, "Action": "sts:AssumeRoleWithWebIdentity", "Condition": { "StringEquals": { "token.actions.githubusercontent.com:aud": "sts.amazonaws.com", "token.actions.githubusercontent.com:sub": "repo:clinicas/citas:ref:refs/heads/main" } }}El mecanismo se llama distinto en cada nube, pero el límite y lo que hay que exigir son los mismos:
| Límite | AWS | Azure | Google Cloud |
|---|---|---|---|
| Red → datos (filtrado) | Security Group / NACL | Network Security Group | Firewall rules / VPC Service Controls |
| Aplicación → secretos | Secrets Manager | Key Vault | Secret Manager |
| CI/CD → prod (federación) | IAM + OIDC | Workload Identity Federation | Workload Identity Federation |
Reglas prácticas#
-
Cada flujo que cruza un límite es candidato a amenazas
Es la regla más rentable del modelado: empieza por esos flujos y aplica STRIDE a cada uno.
-
Pon nombre y datos a cada flujo
“Reserva (nombre, teléfono, motivo) por HTTPS” es analizable; una flecha sin etiqueta no lo es.
-
Dibuja las dos direcciones cuando importen
La respuesta de la API puede filtrar datos aunque la petición sea inofensiva.
-
Incluye los flujos que no son de usuario
Administración (consola, acceso remoto), despliegue (CI/CD), logs (registros de auditoría hacia un archivo centralizado), copias de seguridad y monitorización. Los atacantes los buscan precisamente porque se olvidan.
-
Etiqueta los almacenes con lo que guardan
Clasificación del dato (PII, credenciales, público) y quién puede leerlo.
Tu turno
Modela una app de 3 capas que ya hayas construido
Dibuja el DFD de nivel 1 de esa app (en papel, Excalidraw o Threat Dragon) y marca los límites de confianza.
- ¿Cuántos flujos cruzan un límite? Lístalos.
- ¿Has incluido el pipeline de despliegue y el acceso de administración?
- ¿Algún límite existe en el diagrama pero no en la infraestructura (grupos de seguridad, políticas de identidad, cuentas separadas)?
| Flujo | Origen → destino | Datos | Límite | Control actual |
|---|---|---|---|---|
| … | … | … | … | … |
Cuando lo tengas, aplica STRIDE a cada fila. El caso práctico muestra el resultado completo para Citas.
Reto
El worker de Citas envía recordatorios con un servicio de mensajería gestionado, que los entrega a un operador de SMS. ¿Cruza ese flujo un límite de confianza?
▸Mostrar solución
Sí, y más de uno. El dato sale de tu red privada hacia un servicio gestionado del proveedor (cambia quién lo procesa) y, después, hacia un operador de telefonía que no controlas. Por eso el mensaje debe llevar los datos mínimos (“Tienes cita mañana a las 10:00”), nunca el motivo de la consulta ni notas clínicas.
Reto
¿Por qué los almacenes de datos de un DFD no se conectan directamente entre sí?
▸Mostrar solución
Porque los datos no se mueven solos: siempre hay código que los lee de un sitio y los escribe en otro. Representar ese proceso (aunque sea un servicio gestionado, como la replicación de un almacén de objetos o un job de ETL) hace visible quién tiene permisos sobre ambos almacenes, que es justo lo que interesa analizar.
En resumen#
- El DFD modela datos en movimiento: entidades externas, procesos, almacenes y flujos con dirección.
- Un límite de confianza marca dónde cambia la confianza o el privilegio: red, identidad, tenant, cuenta o proceso.
- Trabaja en nivel 1; baja a nivel 2 solo donde haga falta.
- Cada flujo que cruza un límite es el primer sitio donde buscar amenazas.
- Incluye administración, CI/CD, logs y copias de seguridad, no solo el tráfico de usuarios.
- Los límites del diagrama deben existir en la infraestructura: grupos de seguridad, políticas de identidad (IAM), cuentas separadas.
Referencias#
- OWASP Threat Modeling Cheat Sheet
- Microsoft Threat Modeling Tool: elementos del modelo
- NIST SP 800-154 (borrador): Guide to Data-Centric System Threat Modeling
- GitHub Docs: configurar OpenID Connect en AWS
- Adam Shostack, Threat Modeling: Designing for Security (Wiley, 2014), capítulo 2