¿Sink de registros de GCP borrado? Detectar la evasión
Cómo ciegan a los defensores de Google Cloud: sinks borrados o desviados, exclusiones, buckets de registros, Data Access desactivado, alertas SCC. Qué queda.
En resumen. Un atacante con el rol Owner intentará dejarle a ciegas: DeleteSink o UpdateSink sobre el sink que alimenta su SIEM, CreateExclusion, UpdateBucket / DeleteBucket sobre los buckets de registros, DeleteLog, una actualización de la política de IAM que elimina la configuración de auditoría Data Access (auditConfigDeltas REMOVE) y configuraciones de notificación de Security Command Center borradas. Cada una de estas acciones es a su vez una entrada Admin Activity, conservada 400 días en un bucket que el atacante no puede tocar. Búsquelas primero: su marca de tiempo suele señalar el final de la parte visible del ataque.
En MITRE ATT&CK es T1562.008, Impair Defenses: Disable or Modify Cloud Logs, y T1070, Indicator Removal cuando se borran registros.
Lo que un atacante no puede eliminar
Empecemos por la buena noticia, porque condiciona la investigación. Cloud Logging enruta los registros Admin Activity, System Event y Access Transparency al bucket _Required a través del sink _Required, que no se puede modificar ni borrar; el bucket los conserva 400 días (descripción general del enrutamiento, cuotas).
Así que, incluso tras una toma de control total, el proyecto sigue guardando un registro de cada cambio de configuración, incluidos los que desactivaron todo lo demás. Lo que el atacante sí puede afectar es todo lo que está fuera de _Required: sus exportaciones, sus registros Data Access, sus alertas.
Las técnicas y sus entradas de registro
| Técnica | methodName | Efecto |
|---|---|---|
| Borrar un sink | google.logging.v2.ConfigServiceV2.DeleteSink | Los registros dejan de llegar al SIEM, al bucket de archivo o a BigQuery |
| Modificar un sink | google.logging.v2.ConfigServiceV2.UpdateSink | Destino cambiado (al proyecto del atacante) o filtro restringido para que su actividad no se exporte |
| Añadir una exclusión | google.logging.v2.ConfigServiceV2.CreateExclusion, UpdateExclusion | Las entradas que coinciden se descartan antes de almacenarse (exclusiones) |
| Cambiar un bucket de registros | google.logging.v2.ConfigServiceV2.UpdateBucket, DeleteBucket | Retención acortada, bucket personalizado borrado |
| Borrar un registro | google.logging.v2.LoggingServiceV2.DeleteLog | Entradas de ese registro borradas del bucket _Default (gcloud logging logs delete) |
| Desactivar el registro Data Access | SetIamPolicy con auditConfigDeltas action: REMOVE | Las lecturas dejan de registrarse a partir de ese momento |
| Eliminar las alertas de SCC | securitycenter.googleapis.com DeleteNotificationConfig, UpdateNotificationConfig, CreateMuteConfig | Los hallazgos ya no llegan al SOC o quedan silenciados |
Merece la pena revisar otros dos cambios aunque no sean estrictamente de registro: v1.compute.firewalls abierto a 0.0.0.0/0 (T1562.007) y las políticas de organización relajadas (vea abuso de SetIamPolicy).
Leer el delta de configuración de auditoría
El registro Data Access se configura en la sección auditConfigs de la política de IAM (configurar los registros de auditoría Data Access). Desactivarlo es, por tanto, una llamada SetIamPolicy, y el cambio aparece en el delta de la política junto a los deltas de vinculación:
"policyDelta": {
"auditConfigDeltas": [
{ "action": "REMOVE", "service": "storage.googleapis.com", "logType": "DATA_READ" }
]
}
Un REMOVE para allServices o para storage.googleapis.com justo antes de una ráfaga de actividad es una señal fuerte. Añadir un miembro exento es más sutil: el principal deja de generar registros Data Access para ese servicio mientras todos los demás siguen generándolos.
Lo que dice la marca de tiempo
La evasión de defensas suele llegar tarde en el ataque: el atacante hace lo que vino a hacer y luego limpia. En la práctica:
- Todo lo que ocurre antes del paso de evasión es visible en todas partes (SIEM, bucket del sink, proyecto).
- Todo lo que ocurre después solo es visible en lo que el atacante no pudo cambiar:
_Requireden el proyecto y cualquier sink agregado a nivel de organización sobre el que no tuviera permisos.
Por eso, después de un DeleteSink, no concluya a partir del SIEM que la actividad se detuvo. Exporte directamente desde el proyecto, y desde el sink de la organización si existe.
Diseñar un registro que un atacante no pueda apagar
La solución a largo plazo es de arquitectura, y Google describe las piezas:
- Un sink agregado a nivel de organización o carpeta, que enrute los registros de auditoría de todos los proyectos a un proyecto central sobre el que los responsables de las cargas de trabajo no tengan permisos (almacenamiento centralizado de registros).
- Un bucket de registros con una política de retención bloqueada en ese proyecto (configurar buckets de registros); el bloqueo es irreversible, y un bucket bloqueado no se puede borrar hasta que todas sus entradas hayan alcanzado el periodo de retención.
- Los registros Data Access habilitados a nivel de organización, al menos para IAM, Cloud Storage y Secret Manager.
- Alertas sobre los methodNames de la tabla anterior.
Qué marca el analizador
| Regla | Gravedad | Condición |
|---|---|---|
sink_deleted | Alta | DeleteSink |
sink_modified | Media | UpdateSink |
log_exclusion_created | Media | CreateExclusion o UpdateExclusion |
log_bucket_changed | Media | DeleteBucket o UpdateBucket |
log_deleted | Alta | DeleteLog |
audit_logging_disabled | Alta | Cualquier entrada auditConfigDeltas con action: REMOVE |
scc_notification_removed | Alta | Configuración de notificación de Security Command Center borrada o cambiada, configuración de silenciamiento creada, módulo personalizado borrado |
Cuando estos hallazgos proceden de la misma IP o del mismo principal que hallazgos de acceso anteriores, el analizador genera la correlación crítica de «cadena de ataque». La lista de verificación pide entonces restaurar los sinks y la configuración de auditoría y añadir un sink a nivel de organización hacia un bucket bloqueado.
Cambios legítimos
Los equipos de plataforma sí modifican sinks y exclusiones, normalmente con Terraform, desde la CI, en horario laboral y con un ticket de cambio. Una exclusión que descarta los registros ruidosos del balanceador de carga es normal; una exclusión que filtra por el protoPayload.authenticationInfo.principalEmail de un único usuario no lo es. Lea el filtro.
Preguntas frecuentes
¿Puede un atacante borrar los registros de auditoría de Google Cloud?
No los registros Admin Activity y System Event guardados en el bucket _Required: su sink no se puede modificar ni borrar y el bucket los conserva 400 días. Un atacante con permisos suficientes sí puede borrar los sinks que copian registros a otros destinos, añadir exclusiones, inhabilitar el sink _Default, cambiar los buckets de registros, borrar entradas guardadas en el bucket _Default y desactivar el registro Data Access.
¿Queda registrado el borrado de un sink de registros?
Sí. google.logging.v2.ConfigServiceV2.DeleteSink es una entrada de registro de auditoría Admin Activity, así que el borrado queda registrado en el bucket _Required con quien hizo la llamada y su IP.
Lecturas recomendadas
- Enrutar entradas de registro (descripción general del enrutamiento) — documentación de Google Cloud.
- Prácticas recomendadas para Cloud Audit Logs — documentación de Google Cloud.
- Registros Data Access de GCP: desactivados y puntos ciegos.