Auto-remediación — cerrar el lazo con EventBridge
Cómo convertir un hallazgo de GuardDuty en una respuesta automática con EventBridge y Step Functions, con un ejemplo completo, su patrón de regla, su coste y sus salvaguardas.
Detectar sin responder es tener la alarma sonando mientras nadie está en casa. El tiempo medio hasta la contención —no hasta la detección— es lo que decide cuántos objetos se lleva un atacante. Para ciertos hallazgos de alta confianza, ese tiempo debe medirse en segundos, no en el turno de guardia. Esta nota cierra el lazo: cómo convertir un hallazgo de GuardDutyAmazon GuardDutyServicio gestionado de detección de amenazas de AWS que analiza CloudTrail, VPC Flow Logs y DNS y genera hallazgos (findings). en una respuesta automática con Amazon EventBridge y AWS Step Functions, con el ejemplo completo de Citas, su patrón de regla, su coste y —sobre todo— sus salvaguardas.
El patrón: evento → regla → acción#
Todos los servicios de detección de AWS publican en EventBridgeAmazon EventBridgeBus de eventos sin servidor de AWS que enruta eventos a destinos (Lambda, Step Functions, SNS…) según patrones de coincidencia.. A partir de ahí, el patrón es siempre el mismo:
- Un hallazgo llega al bus (GuardDuty, Security Hub, Config…).
- Una regla con un patrón de evento lo filtra.
- La regla dispara uno o varios destinos: Lambda para una acción corta, o Step Functions para un flujo con varios pasos, reintentos y ramas.
Paso 1 de 5Hallazgo
GuardDuty emite un hallazgo: la clave ci-deploy-legacy se usa desde una IP maliciosa, fuera de AWS. El hallazgo se publica en EventBridge.
¿Lambda o Step Functions?#
- Lambda para una sola acción, idempotente y rápida (desactivar una clave, revocar un SG). Menos piezas.
- Step Functions cuando la respuesta tiene varios pasos, necesita reintentos, ramas condicionales, pasos en paralelo o aprobación humana en medio. Cada transición queda registrada: tienes una traza auditable de qué hizo la respuesta y cuándo. Para un runbook de incidente, es la opción por defecto.
El ejemplo de Citas, de principio a fin#
Escenario: la access key heredada ci-deploy-legacy se filtró en un repositorio público. GuardDuty emite UnauthorizedAccess:IAMUser/MaliciousIPCaller (severidad alta): esa clave opera desde una IP en listas de amenazas, fuera de AWS. Queremos neutralizarla sin esperar a que alguien lea el correo.
1. El patrón de la regla de EventBridge#
Filtra por fuente, tipo y severidad. GuardDuty publica detail.severity como número, así que usamos el operador numérico para capturar todo lo que sea alto o crítico:
{ "source": ["aws.guardduty"], "detail-type": ["GuardDuty Finding"], "detail": { "type": [ "UnauthorizedAccess:IAMUser/MaliciousIPCaller", "UnauthorizedAccess:IAMUser/InstanceCredentialExfiltration.OutsideAWS" ], "severity": [{ "numeric": [">=", 7] }] }}2. El esqueleto de la máquina de estados#
La regla apunta a una state machine con tres pasos. Esbozo en ASL (Amazon States Language), simplificado:
{ "Comment": "Responder a credencial comprometida", "StartAt": "DisableAccessKey", "States": { "DisableAccessKey": { "Type": "Task", "Resource": "arn:aws:states:::aws-sdk:iam:updateAccessKey", "Parameters": { "UserName.$": "$.detail.resource.accessKeyDetails.userName", "AccessKeyId.$": "$.detail.resource.accessKeyDetails.accessKeyId", "Status": "Inactive" }, "Next": "TagResource"14 líneas ocultas
}, "TagResource": { "Type": "Task", "Resource": "arn:aws:states:::aws-sdk:iam:tagUser", "Parameters": { "UserName.$": "$.detail.resource.accessKeyDetails.userName", "Tags": [{ "Key": "quarantine", "Value": "guardduty-auto" }] }, "Next": "Notify" }, "Notify": { "Type": "Task", "Resource": "arn:aws:states:::sns:publish", "Parameters": { "TopicArn": "arn:aws:sns:eu-west-1:111122223333:sec-oncall", "Message.$": "$.detail" }, "End": true } }}Usa las integraciones de SDK de AWS de Step Functions: iam:updateAccessKey desactiva la clave sin escribir código. En paralelo, la misma regla de EventBridge tiene un segundo destino, un topic de SNS, para que la persona de guardia reciba el aviso de inmediato, sin depender de que la máquina termine.
3. Qué detecta, qué no, y qué cuesta#
Un entregable honesto documenta sus límites:
- Uso de la clave desde una IP maliciosa conocida o de forma anómala para esa identidad.
- Exfiltración de credenciales de instancia usadas fuera de AWS. - Reacciona en segundos desde que GuardDuty publica el hallazgo.
- Abuso desde una IP “limpia” que GuardDuty no marca: si no hay hallazgo, no hay regla. - Lo
que pasó antes del hallazgo (hay latencia entre el uso y la detección). - Credenciales
obtenidas con
GetFederationToken: sobreviven a desactivar la access key. - Acciones ya ejecutadas: la remediación corta el futuro, no deshace el pasado.
- EventBridge: la entrega de eventos de servicios de AWS al bus por defecto no se factura. - Step Functions (Standard): se cobra por transición de estado; tres pasos por incidente es calderilla. - Lambda / SNS: dentro de capa gratuita para este volumen. - El coste real está en GuardDuty (por volumen de datos analizados), no en la automatización.
El radio de impacto: la parte peligrosa#
La auto-remediación es una identidad con permisos para desactivar llaves y etiquetar recursos reaccionando a eventos. Si se equivoca o alguien la manipula, el daño es tuyo, no del atacante.
Tu turno
Construye y prueba un lazo de remediación
En tu cuenta sandbox (nunca en producción ni contra terceros):
- Crea una regla de EventBridge con el patrón de arriba (ajusta los tipos a lo que puedas detonar).
- Apúntala primero a un SNS que solo te notifique (“modo dry-run”): ¿qué habría hecho?
- Detona el hallazgo con las muestras de GuardDuty o con Stratus Red Team.
- Añade la máquina de estados de tres pasos y vuelve a detonar. Mide el tiempo desde el hallazgo hasta la clave inactiva.
- Escribe media página: qué detecta, qué no, su coste y su radio de impacto.
Guarda ese documento: es, literalmente, el entregable de la Fase 2.
Reto
Desactivaste la access key del atacante. ¿Por qué podría seguir dentro?
▸Mostrar solución
Porque desactivar la clave no invalida las credenciales temporales que ya hubiera obtenido (p.
ej. con sts:GetFederationToken o asumiendo un rol): esos tokens siguen vivos hasta que expiran.
La respuesta completa incluye revisar y, si procede, revocar sesiones activas, además de
investigar qué hizo antes.
Reto
¿Por qué notificar por SNS en paralelo y no al final de la máquina de estados?
▸Mostrar solución
Para que el aviso al humano no dependa de que la remediación termine bien. Si un paso de Step Functions falla o se atasca, la persona de guardia ya recibió el contexto por el destino paralelo de EventBridge y puede intervenir a mano.
En resumen#
- Todo hallazgo pasa por EventBridge: evento → regla (patrón) → destino (Lambda o Step Functions).
- Step Functions para respuestas de varios pasos, con reintentos, ramas y una traza auditable; Lambda para una acción simple.
- Auto-remedia solo tipos de alta fidelidad; para el resto, notifica y que decida un humano.
- Documenta siempre qué detecta, qué no y qué cuesta: la auto-remediación corta el futuro, no deshace el pasado, y no ve lo que GuardDuty no marca.
- El radio de impacto es real: mínimo privilegio en el rol, excluye lo crítico, empieza en dry-run y prueba en staging.