Sink de journaux GCP supprimé ? Détecter l'évasion
Comment un attaquant aveugle la défense Google Cloud : sinks supprimés ou redirigés, exclusions, buckets de journaux, Data Access coupé. Ce qui reste.
En bref. Un attaquant disposant du rôle Owner cherchera à vous aveugler : DeleteSink ou UpdateSink sur le sink qui alimente votre SIEM, CreateExclusion, UpdateBucket / DeleteBucket sur des buckets de journaux, DeleteLog, une mise à jour de stratégie IAM qui retire la configuration d'audit Data Access (auditConfigDeltas REMOVE), et la suppression des configurations de notification de Security Command Center. Chacune de ces actions est elle-même une entrée Admin Activity, conservée 400 jours dans un bucket auquel l'attaquant ne peut pas toucher. Cherchez-les en premier : leur horodatage marque souvent la fin de la partie visible de l'attaque.
Dans MITRE ATT&CK, il s'agit de T1562.008, Impair Defenses: Disable or Modify Cloud Logs, et de T1070, Indicator Removal quand des journaux sont supprimés.
Ce qu'un attaquant ne peut pas retirer
Commençons par la bonne nouvelle, car elle structure l'investigation. Cloud Logging achemine les journaux Admin Activity, System Event et Access Transparency vers le bucket _Required via le sink _Required, qui ne peut être ni modifié ni supprimé ; le bucket les conserve 400 jours (vue d'ensemble du routage, quotas).
Ainsi, même après une prise de contrôle complète, le projet conserve la trace de chaque changement de configuration, y compris ceux qui ont désactivé tout le reste. Ce que l'attaquant peut atteindre, c'est tout ce qui se trouve hors de _Required : vos exports, vos journaux Data Access, vos alertes.
Les techniques et leurs entrées de journal
| Technique | methodName | Effet |
|---|---|---|
| Supprimer un sink | google.logging.v2.ConfigServiceV2.DeleteSink | Les journaux cessent d'arriver dans le SIEM, le bucket d'archive ou BigQuery |
| Modifier un sink | google.logging.v2.ConfigServiceV2.UpdateSink | Destination changée (vers le projet de l'attaquant) ou filtre restreint pour que son activité ne soit pas exportée |
| Ajouter une exclusion | google.logging.v2.ConfigServiceV2.CreateExclusion, UpdateExclusion | Les entrées correspondantes sont écartées avant stockage (exclusions) |
| Modifier un bucket de journaux | google.logging.v2.ConfigServiceV2.UpdateBucket, DeleteBucket | Rétention raccourcie, bucket personnalisé supprimé |
| Supprimer un journal | google.logging.v2.LoggingServiceV2.DeleteLog | Entrées de ce journal supprimées du bucket _Default (gcloud logging logs delete) |
| Couper la journalisation Data Access | SetIamPolicy avec auditConfigDeltas action: REMOVE | Les lectures ne sont plus enregistrées à partir de ce moment |
| Retirer les alertes SCC | securitycenter.googleapis.com DeleteNotificationConfig, UpdateNotificationConfig, CreateMuteConfig | Les constats n'arrivent plus au SOC, ou sont mis en sourdine |
Deux autres changements méritent d'être examinés même s'ils ne relèvent pas strictement de la journalisation : v1.compute.firewalls ouvert à 0.0.0.0/0 (T1562.007), et les règles d'administration assouplies (voir l'abus de SetIamPolicy).
Lire le delta de configuration d'audit
La journalisation Data Access se configure dans la section auditConfigs de la stratégie IAM (configurer les journaux d'audit Data Access). La désactiver est donc un appel SetIamPolicy, et le changement apparaît dans le delta de stratégie à côté des deltas de liaison :
"policyDelta": {
"auditConfigDeltas": [
{ "action": "REMOVE", "service": "storage.googleapis.com", "logType": "DATA_READ" }
]
}
Un REMOVE pour allServices ou pour storage.googleapis.com juste avant une rafale d'activité est un signal fort. Ajouter un membre exempté est plus subtil : ce principal cesse de produire des journaux Data Access pour le service, alors que tous les autres continuent.
Ce que dit l'horodatage
L'évasion des défenses intervient souvent tard dans l'attaque : l'attaquant fait ce pour quoi il est venu, puis nettoie. En pratique :
- Tout ce qui précède l'étape d'évasion est visible partout (SIEM, bucket du sink, projet).
- Tout ce qui suit n'est visible que dans ce que l'attaquant n'a pas pu modifier :
_Requireddans le projet, et tout sink agrégé au niveau de l'organisation sur lequel il n'avait aucun droit.
Après un DeleteSink, ne concluez donc pas à partir du SIEM que l'activité s'est arrêtée. Exportez directement depuis le projet, et depuis le sink de l'organisation s'il existe.
Concevoir une journalisation qu'un attaquant ne peut pas couper
La correction de fond est architecturale, et Google en décrit les briques :
- Un sink agrégé au niveau de l'organisation ou du dossier, qui achemine les journaux d'audit de tous les projets vers un projet central sur lequel les responsables des charges de travail n'ont aucun droit (stockage centralisé des journaux).
- Un bucket de journaux avec une règle de rétention verrouillée dans ce projet (configurer les buckets de journaux) ; le verrouillage est irréversible, et un bucket verrouillé ne peut pas être supprimé tant que chaque entrée n'a pas atteint la durée de rétention.
- Des journaux Data Access activés au niveau de l'organisation, au minimum pour IAM, Cloud Storage et Secret Manager.
- Des alertes sur les methodNames du tableau ci-dessus.
Ce que l'analyseur signale
| Règle | Sévérité | Condition |
|---|---|---|
sink_deleted | Haute | DeleteSink |
sink_modified | Moyenne | UpdateSink |
log_exclusion_created | Moyenne | CreateExclusion ou UpdateExclusion |
log_bucket_changed | Moyenne | DeleteBucket ou UpdateBucket |
log_deleted | Haute | DeleteLog |
audit_logging_disabled | Haute | Toute entrée auditConfigDeltas avec action: REMOVE |
scc_notification_removed | Haute | Configuration de notification Security Command Center supprimée ou modifiée, règle de mise en sourdine créée, module personnalisé supprimé |
Quand ces constats proviennent de la même IP ou du même principal que des constats d'accès antérieurs, l'analyseur lève la corrélation critique « chaîne d'attaque ». La checklist demande alors de restaurer les sinks et la configuration d'audit, et d'ajouter un sink au niveau de l'organisation vers un bucket verrouillé.
Les changements légitimes
Les équipes plateforme modifient bien sûr des sinks et des exclusions, en général via Terraform, depuis la CI, aux heures ouvrées, avec un ticket de changement. Une exclusion qui écarte les journaux bruyants d'un équilibreur de charge est normale ; une exclusion qui cible le protoPayload.authenticationInfo.principalEmail d'un seul utilisateur ne l'est pas. Lisez le filtre.
Questions fréquentes
Un attaquant peut-il supprimer les journaux d'audit Google Cloud ?
Pas les journaux Admin Activity et System Event conservés dans le bucket _Required : son sink ne peut être ni modifié ni supprimé et le bucket les garde 400 jours. Un attaquant disposant de droits suffisants peut en revanche supprimer les sinks qui copient les journaux ailleurs, ajouter des exclusions, désactiver le sink _Default, modifier des buckets de journaux, supprimer des entrées conservées dans le bucket _Default et couper la journalisation Data Access.
La suppression d'un sink est-elle elle-même journalisée ?
Oui. google.logging.v2.ConfigServiceV2.DeleteSink est une entrée de journal d'audit Admin Activity : la suppression est enregistrée dans le bucket _Required avec l'appelant et son IP.
Pour aller plus loin
- Acheminer les entrées de journal (vue d'ensemble du routage) — documentation Google Cloud.
- Bonnes pratiques pour Cloud Audit Logs — documentation Google Cloud.
- Journaux Data Access GCP : désactivés par défaut, et autres angles morts.