Exfiltración de GCS y BigQuery: pruebas en la auditoría
Demuestre o descarte un robo de datos de Cloud Storage y BigQuery: storage.objects.get masivo, buckets públicos, claves HMAC, copias a otro proyecto, imágenes.
En resumen. El robo de datos en Google Cloud se ve en cuatro lugares: lecturas (ráfagas de storage.objects.get, solo con registros Data Access), exposición (allUsers añadido a la política de un bucket o conjunto de datos, siempre registrado), copias a otro proyecto (trabajos de BigQuery con un destino ajeno, imágenes e instantáneas compartidas) y credenciales por la puerta de atrás (claves HMAC). Establezca la ventana de exposición a partir de los registros Admin Activity aunque las lecturas sean invisibles, y dígalo explícitamente en el informe.
«¿Se llevaron datos?» es la primera pregunta que harán el equipo jurídico y la dirección, y la que los registros de auditoría responden de forma menos completa. Esto es lo que cada registro puede y no puede demostrar.
Lecturas: storage.objects.get
Cada descarga de un objeto a través de la API JSON o XML de Cloud Storage es una llamada storage.objects.get, registrada como registro de auditoría Data Access (DATA_READ) si el registro Data Access estaba habilitado para Cloud Storage (registros de auditoría de Cloud Storage). La entrada indica el objeto en resourceName (projects/_/buckets/BUCKET/objects/NAME), el principal, la IP de origen y el user agent.
logName:"cloudaudit.googleapis.com%2Fdata_access"
protoPayload.methodName="storage.objects.get"
resource.labels.bucket_name="BUCKET"
Qué extraer:
- Volumen y ritmo por principal: cien objetos en pocos minutos de un principal que normalmente lee cuatro al día.
- Nombres de objeto: le dicen qué se llevaron (
customers/…,backups/…). - El principal: una cuenta personal, una clave de cuenta de servicio desde una IP desconocida o un agente de servicio haciendo su trabajo normal.
- Además,
storage.objects.list(reconocimiento antes de la descarga) y, si el atacante copia en lugar de descargar,storage.objects.create/ rewrite en un bucket de destino que controla.
Esto corresponde a T1530, Data from Cloud Storage. La salvedad es importante: los registros Data Access están desactivados por defecto, y Google advierte que habilitarlos para Cloud Storage puede romper en algunos casos las descargas autenticadas desde el navegador (configurar los registros de auditoría Data Access), por lo que muchos proyectos nunca los activan. Vea limitaciones de los registros Data Access.
Exposición: allUsers y allAuthenticatedUsers
Hacer público un bucket es un cambio de política; por tanto, Admin Activity; por tanto, siempre registrado. Para los buckets el método es storage.setIamPermissions; el delta está en serviceData.policyDelta.bindingDeltas:
{ "action": "ADD", "role": "roles/storage.objectViewer", "member": "allUsers" }
En cuanto allUsers puede leer un bucket, las descargas anónimas son posibles y no las verá: Google indica que Cloud Audit Logs no registra el acceso a objetos públicos (registros de auditoría de Cloud Storage). Solo los registros de uso de Cloud Storage, si estaban configurados, recogen ese tráfico. La conclusión honesta es una ventana de exposición: desde el ADD hasta el REMOVE (o hasta ahora), el contenido estuvo al alcance de cualquiera que conociera o adivinara el nombre del bucket. Esa ventana, y la lista de objetos presentes en el bucket durante ella, es lo que necesita una evaluación de protección de datos. La página de Google hacer públicos los datos explica el mecanismo; la prevención de acceso público lo bloquea.
La misma lógica se aplica a allUsers en conjuntos de datos de BigQuery, servicios de Cloud Run, Cloud Functions o imágenes.
Puertas traseras: claves HMAC
storage.hmacKeys.create crea un par clave de acceso / secreto para la API XML compatible con S3. Es persistencia más que exfiltración: la clave sigue funcionando después de rotar las demás credenciales de la cuenta de servicio. Trate cada clave HMAC creada durante el incidente como controlada por el atacante (T1098.001).
BigQuery: copias a otro proyecto
BigQuery es distinto en un aspecto útil: los registros de auditoría Data Access están habilitados por defecto para algunos servicios de BigQuery (descripción general de Cloud Audit Logs). Los trabajos (consultas, copias, extracciones) se registran con su configuración (registros de auditoría de BigQuery).
La señal que hay que buscar es un destino fuera del proyecto: un trabajo de copia o de consulta cuya destinationTable pertenece a otro ID de proyecto. Un atacante con acceso de lectura a su conjunto de datos y acceso de escritura a su propio proyecto puede mover una tabla entera con una sola llamada: T1537, Transfer Data to Cloud Account. Revise también los trabajos de extracción (destinationUris que apuntan a buckets gs:// que no son suyos) y los cambios de política de los conjuntos de datos (metadata.datasetChange.bindingDeltas).
Imágenes de disco e instantáneas
Compartir una imagen de disco o una instantánea con otro proyecto saca una copia del disco entero, bases de datos y credenciales incluidas. Busque setIamPolicy sobre compute.images, compute.snapshots, compute.disks y compute.machineImages, y compruebe qué miembros se añadieron.
Salida de red
Los datos que lee una VM comprometida y envía al exterior no aparecen en absoluto en los registros de auditoría. VPC Flow Logs es la única fuente: bytes enviados por IP externa.
Qué marca el analizador
| Regla | Gravedad | Condición |
|---|---|---|
bulk_object_reads | Alta | 100 storage.objects.get del mismo principal en 10 minutos (con cualquier resultado) |
public_access_granted | Crítica | allUsers / allAuthenticatedUsers añadido a cualquier política de IAM |
bq_foreign_export | Alta | Trabajo de copia o de consulta de BigQuery cuya tabla de destino está en otro proyecto |
image_shared | Media | Cambio en la política de IAM de una imagen, instantánea, disco o imagen de máquina |
hmac_key_created | Media | storage.hmacKeys.create |
flow_large_egress (análisis) | Media | 1 GiB o más enviado desde sus VM a una misma IP pública (VPC Flow Logs) |
Límites de las reglas actuales: los trabajos de extracción de BigQuery hacia buckets externos todavía no se marcan, y una cuenta de servicio de ETL muy activa que lee de forma continua puede superar el umbral de lecturas masivas. La herramienta también avisa cuando una exportación no contiene registros Data Access, ya que bulk_object_reads no puede activarse sin ellos.
Redactar las conclusiones
Para cada conjunto de datos o bucket implicado, indique por separado: qué se ha demostrado que se leyó (nombres de objeto, principal, hora), qué estuvo expuesto (ventana, objetos presentes), qué se copió (proyecto de destino, tabla, imagen) y qué no se puede saber por falta de registros. La lista de remediación de la herramienta pide esta evaluación, porque obligaciones de notificación como el plazo de 72 horas del RGPD pueden depender de ella.
Preguntas frecuentes
¿Puedo ver qué archivos se descargaron de un bucket de Cloud Storage?
Solo si los registros de auditoría Data Access (DATA_READ) estaban habilitados para Cloud Storage antes de la descarga. En ese caso, cada lectura genera una entrada storage.objects.get con el nombre del objeto, el principal y la IP de origen. Sin ellos, las lecturas no se registran en los registros de auditoría.
¿Cómo sé si un bucket se hizo público?
Busque entradas Admin Activity (storage.setIamPermissions en el caso de los buckets) cuyo delta de política añade allUsers o allAuthenticatedUsers. Los registros Admin Activity están siempre activos, así que este cambio queda registrado aunque las lecturas no.
Lecturas recomendadas
- Cloud Audit Logs con Cloud Storage — documentación de Google Cloud.
- Descripción general de los registros de auditoría de BigQuery — documentación de Google Cloud.
- Abuso de SetIamPolicy: detectar Owner y miembros externos.