Exfiltración de datos en Azure Storage: SAS y logs de blobs
Investiga una exfiltración en Azure Storage: listAccountSas y listKeys en el Activity Log, ráfagas de GetBlob en los logs de blobs, hashes de SAS y qué rotar.
En resumen. La exfiltración desde almacenamiento deja dos tipos de rastros. En el Activity Log: listKeys/action, listAccountSas/action, listServiceSas/action y cambios de configuración que abren la cuenta (allowBlobPublicAccess: true, cortafuegos con defaultAction: Allow). En los logs de recursos de almacenamiento (StorageRead / StorageBlobLogs, solo si están activados): solicitudes GetBlob con la IP del autor, el tipo de autenticación, un hash de la SAS o del token, la clave del objeto y los bytes devueltos. Una SAS firmada en el cliente con una clave de cuenta nunca se registra al crearse; solo la ves cuando se usa. Rotar las dos claves de la cuenta revoca las SAS de cuenta y de servicio.
La cuenta de almacenamiento es donde están los datos. Tras un compromiso en la nube, la pregunta casi siempre es «¿qué se llevaron?», y en el almacenamiento de blobs esa pregunta tiene respuesta, siempre que existiera la configuración de diagnóstico adecuada.
Cómo llegan los atacantes a los datos
| Vía | Rastro en el plano de control (Activity Log) | Rastro en el plano de datos (log de almacenamiento) |
|---|---|---|
| Leer las claves de la cuenta y firmar su propia SAS sin conexión | Microsoft.Storage/storageAccounts/listKeys/action | GetBlob con autenticación SAS o AccountKey |
| Pedir a Azure Resource Manager que genere una SAS de cuenta o de servicio | listAccountSas/action / listServiceSas/action | GetBlob con autenticación SAS, statusText SASSuccess |
| Usar una identidad de Entra con un rol de datos (Storage Blob Data Reader…) | Posiblemente antes un roleAssignments/write | GetBlob con OAuth, object ID del solicitante |
| Hacer público un contenedor | storageAccounts/write o containers/write con acceso público | GetBlob con Anonymous |
| Abrir el cortafuegos del almacenamiento | storageAccounts/write con defaultAction: Allow o acceso de red público habilitado | Solicitudes desde IP que antes estaban bloqueadas |
MITRE ATT&CK registra la recopilación como T1530 Data from Cloud Storage. Storm-0501, según documenta Microsoft Threat Intelligence, usó listkeys/action y exfiltró con AzCopy antes de borrar en masa cuentas de almacenamiento.
El problema de las SAS: su creación es invisible
Una firma de acceso compartido (SAS) es una URL firmada. La documentación de Microsoft no deja lugar a dudas: no es posible auditar la generación de tokens SAS, y Azure Storage no hace ningún seguimiento de ellos (información general de SAS). Una SAS firmada en local con una clave de cuenta no genera ningún evento. Lo que sí puedes ver:
listKeys/action: alguien obtuvo las claves (y podía firmar SAS sin límite y sin conexión).listAccountSas/action/listServiceSas/action: alguien pidió a ARM que firmara una. El cuerpo de la solicitud muestra servicios, permisos, inicio y caducidad solicitados.- Cada uso de una SAS, en los logs de recursos de almacenamiento, si están activados.
La recomendación de Microsoft de no permitir la autorización con clave compartida (Shared Key) en las cuentas que no la necesitan elimina toda la categoría: sin Shared Key, las SAS de cuenta y de servicio dejan de funcionar.
Leer StorageBlobLogs
La referencia de supervisión de Blob Storage documenta los campos. Los que importan para la exfiltración:
| Campo (exportación a almacenamiento) | Ejemplo | Por qué |
|---|---|---|
operationName | GetBlob, ListBlobs, PutBlob, DeleteBlob | Qué pasó |
callerIpAddress | 203.0.113.66:51234 | Desde dónde (fíjate en el puerto como sufijo) |
identity.type | SAS, AccountKey, OAuth, Anonymous | Cómo se autorizó la solicitud |
identity.tokenHash | key1(…),SasSignature(…) | Qué clave firmó la SAS y un SHA-256 de la propia SAS |
identity.requester.objectId | GUID | La identidad de Entra, en OAuth |
properties.objectKey | /account/container/blob | Qué blob |
properties.responseBodySize | bytes | Cuánto salió |
properties.userAgentHeader | AzCopy/10.x … | Qué herramienta |
statusCode / statusText | 200 / SASSuccess | Éxito o fallo |
El hash SasSignature(…) es tu pivote: todas las solicitudes con el mismo hash usaron el mismo token SAS, lo tuviera quien lo tuviera. El analizador lo usa como entidad para los accesos SAS (se muestra como sas:<prefijo del hash>), de modo que una SAS filtrada aparece como una sola entidad con sus IP y su total de bytes.
Los logs de almacenamiento son voluminosos. El analizador deja fuera de la tabla de eventos las lecturas rutinarias, pero las cuenta y evalúa todas.
Qué marca el analizador
| Regla | Detecta | Nivel |
|---|---|---|
AZ-ST-001 | SAS de cuenta o de servicio generada mediante ARM (listAccountSas, listServiceSas) | Alto |
AZ-ST-002 | Claves de la cuenta listadas o regeneradas | Bajo |
AZ-ST-003 | Acceso anónimo a blobs habilitado en la cuenta o en un contenedor | Alto |
AZ-ST-004 | Cortafuegos del almacenamiento abierto a todas las redes | Medio |
AZ-ST-005 | Descarga masiva: al menos 50 blobs distintos leídos por la misma identidad desde la misma IP en 60 minutos, con el total de bytes | Alto |
AZ-ST-006 | Lecturas anónimas de blobs | Medio |
AZ-VM-005 | Disco o snapshot exportado con una URL SAS | Alto |
AZ-ST-002 es bajo a propósito: el explorador de almacenamiento del portal, las Function Apps y las herramientas de copia de seguridad listan claves continuamente. Se vuelve interesante junto a otros hallazgos.
Dimensionar la exposición
La notificación de brechas necesita hechos, no «el atacante tenía acceso a la cuenta». Constrúyelos con los logs:
- Enumera los blobs leídos por la entidad / hash de SAS / IP sospechosos: claves de objeto, tamaños, marcas de tiempo. El analizador Azure Forensics los agrupa por identidad, IP y cuenta, con el total de bytes.
- Separa lecturas de listados.
ListBlobsrevela nombres;GetBlobrevela contenido. - Comprueba las lecturas parciales. Un campo
downloadRangeindica que solo se transfirió parte del blob. - Comprueba escrituras y eliminaciones (
StorageWrite,StorageDelete): los actores de tipo ransomware borran después de copiar. - Comprueba los demás servicios. Los logs de blobs no cubren Files, Queues ni Tables; cada uno tiene sus propias categorías de logs.
Por ejemplo, en el ejemplo ficticio del sitio, una SAS usada desde una IP lee 330 blobs de copia de seguridad distintos en 18 minutos, unos 48,6 GB en total. Esa cifra, por contenedor, es la que necesitan los equipos jurídicos.
Remediación
- Rota las dos claves de la cuenta de almacenamiento. Microsoft documenta que las SAS de cuenta y de servicio se firman con la clave de la cuenta, así que regenerarla las invalida. Las SAS de delegación de usuario se revocan revocando las claves de delegación de usuario.
- Desactiva el acceso anónimo y restaura el cortafuegos (acción predeterminada Deny, puntos de conexión privados).
- Valora no permitir la autorización con Shared Key.
- Activa ya
StorageRead/StorageWrite/StorageDeleteen el servicio de blobs de las cuentas sensibles. - Determina qué datos se leyeron, por las obligaciones de notificación (por ejemplo, la notificación a la autoridad de control en 72 horas del RGPD, artículo 33).