PowerShell absichern — Protokollierung, AMSI, Sprachmodi und JEA
· Go Komura · PowerShell, Sicherheit, Windows, Protokollierung, Auditierung, Unternehmens-IT, Berechtigungsverwaltung, Betriebsoptimierung
Nach einer Reihe von Berichten, dass „PowerShell beim Eindringen missbraucht wurde“, versuchen manche Organisationen, die Nutzung von PowerShell im gesamten Unternehmen komplett zu verbieten. Das zahlt sich jedoch weder in der Wirksamkeit noch bei den geschäftlichen Auswirkungen aus. PowerShell ist selbst die Verwaltungsgrundlage von Windows, und es zu stoppen stoppt auch Ihre betriebliche Automatisierung. Ein Angreifer kann währenddessen dasselbe über andere Wege erreichen.
Die realistische Strategie lautet nicht Verbot, sondern Sichtbarkeit und Einschränkung. Glücklicherweise bringt PowerShell 5.0 und höher Funktionen für die verteidigende Seite mit: Script Block Logging, das selbst verschleierten Code in expandierter Form aufzeichnet; AMSI, das den Inhalt vor der Ausführung an Ihr Antivirenprodukt übergibt; Sprachmodi, die die ausführbare Syntax selbst einschränken; und JEA, das „nur die tatsächlich benötigten Vorgänge“ delegiert. Kombinieren Sie diese, erreichen Sie einen prüfbaren Zustand, ohne den Betrieb zu stoppen.
Dieser Artikel fasst die Einstellungen zusammen, die Sie anwenden sollten, um PowerShell in einer internen Windows-Umgebung sicher weiterzunutzen, geordnet nach Wirksamkeit. Ausführungsrichtlinie und Signierung werden in „PowerShell-Ausführungsrichtlinie und Skriptsignierung“ behandelt; dieser Artikel knüpft daran an.
1. Das Wichtigste zuerst
- Oberste Priorität hat die Aktivierung von Script Block Logging. Ausgeführter Code wird im Ereignisprotokoll aufgezeichnet, und verschleierter Code bleibt in expandierter Form erhalten (Ereignis-ID 4104).1
- Aktivieren Sie zugleich die Transkription. Sitzungsaufzeichnungen einschließlich Ein- und Ausgabe lassen sich auf einer nur beschreibbaren Freigabe zusammenführen.1
- Prüfen Sie nach dem Aktivieren der Protokollierung auch Ihre Protokollgrößen-Einstellungen. Bei den Standardwerten läuft es in kurzer Zeit über.1
- AMSI übergibt das Skript vor der Ausführung an Ihr Antivirenprodukt. Es ist ab PowerShell 5.0, ab Windows 10, aktiv.2
- Deaktivieren Sie die alte PowerShell-2.0-Engine. Solange sie verbleibt, besteht die Möglichkeit, in eine alte Engine zu wechseln, in der weder Protokollierung noch AMSI greifen.3
- Die Ausführungsrichtlinie ist keine Sicherheitsgrenze. Microsoft stellt dies ausdrücklich klar. Machen Sie sie nicht zum Kern Ihrer Verteidigung.4
- Verwenden Sie Sprachmodi als Folge von WDAC/AppLocker. Manuell gesetzt lassen sie sich umgehen und wirken nicht als Sicherheitsfunktion.5
- Verwenden Sie JEA zur Delegation von Berechtigungen. Erlauben Sie „nur diesen Parameter, dieses Befehls“, und halten Sie den Betrieb aufrecht, ohne Administratorrechte zu vergeben.6
2. Was schützen Sie? — Erst Sichtbarkeit, dann Einschränkung
Legen Sie vor der Auflistung von Maßnahmen Prioritäten fest.
| Stufe | Was zu tun ist | Wirkung |
|---|---|---|
| 1. Sichtbarkeit | Script Block Logging, Transkription | Sie erkennen, was passiert ist. Eine nachträgliche Untersuchung wird möglich |
| 2. Grundlegende Entschärfung | PowerShell 2.0 deaktivieren, aktuell halten, AMSI verifizieren | Wege schließen, die die Prüfung umgehen |
| 3. Berechtigungen einschränken | Delegation über JEA, Reduzierung von Administratorrechten | Den Schadensradius begrenzen |
| 4. Ausführung einschränken | WDAC/AppLocker + eingeschränkter Sprachmodus | Nicht genehmigten Code von vornherein an der Ausführung hindern |
In vielen Organisationen verbessert allein die Umsetzung von 1 und 3 die Lage erheblich. Punkt 4 hat hohe Einführungskosten und ist ein Bereich, den Sie voranbringen sollten, während Sie die Auswirkungen auf den Betrieb überprüfen.
3. Protokollierung aktivieren — 4104 ist am wichtigsten
Die Protokollierung von PowerShell umfasst drei Ebenen.1
| Art | Was aufgezeichnet wird | Ereignis-ID |
|---|---|---|
| Modulprotokollierung | Details der Pipeline-Ausführung für angegebene Module | 4103 |
| Script Block Logging | Der Text des ausgeführten Codes (nach Entschleierung) | 4104 |
| Zielprotokoll | 5.1 schreibt nach Microsoft-Windows-PowerShell/Operational, 7 nach PowerShellCore/Operational |
— |
| Transkription | Zeichnet Ein- und Ausgabe der Sitzung in eine Textdatei auf | — (Dateiausgabe) |
All dies lässt sich über Gruppenrichtlinie unter „Computerkonfiguration > Administrative Vorlagen > Windows-Komponenten > Windows PowerShell“ konfigurieren. Sie können die Werte auch direkt in der Registrierung setzen.1
# Script Block Logging aktivieren (erfordert Administratorrechte; normalerweise per GPO ausgerollt)
$key = 'HKLM:\SOFTWARE\Policies\Microsoft\Windows\PowerShell\ScriptBlockLogging'
New-Item -Path $key -Force | Out-Null
# -Type ist ein vom Registrierungsanbieter hinzugefügter dynamischer Parameter. Damit lässt sich der Werttyp (DWord) explizit angeben
Set-ItemProperty -Path $key -Name 'EnableScriptBlockLogging' -Value 1 -Type DWord
# PowerShell 7 (pwsh) sieht auf einen anderen Richtlinienschlüssel. Beide setzen
$key = 'HKLM:\SOFTWARE\Policies\Microsoft\PowerShellCore\ScriptBlockLogging'
New-Item -Path $key -Force | Out-Null
Set-ItemProperty -Path $key -Name 'EnableScriptBlockLogging' -Value 1 -Type DWord
# Transkription aktivieren und auf einer nur beschreibbaren Freigabe zusammenführen
$key = 'HKLM:\SOFTWARE\Policies\Microsoft\Windows\PowerShell\Transcription'
New-Item -Path $key -Force | Out-Null
Set-ItemProperty -Path $key -Name 'EnableTranscripting' -Value 1 -Type DWord
Set-ItemProperty -Path $key -Name 'OutputDirectory' -Value '\\logsrv\pstranscripts$'
Set-ItemProperty -Path $key -Name 'EnableInvocationHeader' -Value 1 -Type DWord
# Die Transkription hat auf der PowerShell-7-Seite einen eigenen Schlüssel. Dieselben Werte schreiben
$key = 'HKLM:\SOFTWARE\Policies\Microsoft\PowerShellCore\Transcription'
New-Item -Path $key -Force | Out-Null
Set-ItemProperty -Path $key -Name 'EnableTranscripting' -Value 1 -Type DWord
Set-ItemProperty -Path $key -Name 'OutputDirectory' -Value '\\logsrv\pstranscripts$'
Set-ItemProperty -Path $key -Name 'EnableInvocationHeader' -Value 1 -Type DWord
PowerShell 7 liest die Richtlinie unter PowerShellCore, nicht unter Windows\PowerShell. Konfigurieren Sie nur die 5.1-Seite und halten das für erledigt, fehlen Aufzeichnungen von unter pwsh ausgeführten Skripten vollständig. Schreiben Sie sowohl für Script Block Logging als auch für Transkription dieselben Werte in beide Schlüssel (rollen Sie es per GPO aus, konfigurieren Sie jeweils die entsprechende Vorlage).
Der Wert von Script Block Logging liegt in seiner Widerstandsfähigkeit gegen Verschleierung. Ob der Befehl Base64-kodiert oder durch Zeichenkettenverkettung zusammengesetzt war — aufgezeichnet wird der zum Ausführungszeitpunkt expandierte Inhalt.1 Ob Sie bei einer Vorfalluntersuchung rekonstruieren können, „was ausgeführt wurde“, entscheidet sich daran, ob diese Einstellung vorhanden ist.
Zur Überprüfung der Aufzeichnungen verwenden Sie Get-WinEvent (siehe „Ereignisprotokolle mit Get-WinEvent praxisnah untersuchen“).
# Script-Block-Protokolle des letzten Tages prüfen.
# Windows PowerShell (5.1) und PowerShell 7 schreiben in unterschiedliche Protokolle,
# deshalb beide abdecken
Get-WinEvent -FilterHashtable @{
LogName = 'Microsoft-Windows-PowerShell/Operational', 'PowerShellCore/Operational'
ID = 4104
StartTime = (Get-Date).AddDays(-1)
} -ErrorAction SilentlyContinue |
Select-Object TimeCreated, LogName, @{ n='Script'; e={ $_.Message } } -First 20
Prüfen Sie nach dem Aktivieren unbedingt die Protokollgröße. Bei der Standardgröße läuft es innerhalb von Stunden bis Tagen über, und im Bedarfsfall ist nichts mehr vorhanden.
Get-WinEvent -ListLog 'Microsoft-Windows-PowerShell/Operational', 'PowerShellCore/Operational' |
Select-Object LogName, MaximumSizeInBytes, RecordCount
wevtutil sl Microsoft-Windows-PowerShell/Operational /ms:1073741824 # Beispiel: auf 1 GB erweitern
wevtutil sl PowerShellCore/Operational /ms:1073741824 # die PowerShell-7-Seite nicht vergessen
Der entscheidende Punkt beim Transkript-Ausgabeort ist, dass es sich um eine Freigabe handeln sollte, auf die Benutzer nur schreiben, aber nicht löschen oder überschreiben können. Legen Sie es lokal ab, wird es bei einem kompromittierten Rechner schlicht gelöscht.
4. Umgehungswege schließen — PowerShell 2.0 und AMSI
Über AMSI (Antimalware Scan Interface) übergibt PowerShell 5.0 und höher den Inhalt eines Skripts unmittelbar vor der Ausführung an das Antivirenprodukt, sodass er in entschleierter Form geprüft werden kann.2 Verwenden Sie ein unterstützendes Produkt, einschließlich Microsoft Defender, funktioniert dies ohne zusätzliche Konfiguration.
Das Problem ist, dass die alte Engine über keinen solchen Mechanismus verfügt. Bleibt die Engine Windows PowerShell 2.0 aktiviert, besteht mit powershell.exe -Version 2 weiterhin die Möglichkeit, in eine Umgebung zu wechseln, in der weder Protokollierung noch AMSI greifen. Diese Funktion ist veraltet, und ihre Deaktivierung wird empfohlen.3
# Status der PowerShell-2.0-Engine prüfen und deaktivieren (erfordert Administratorrechte; ein Neustart kann nötig sein)
Get-WindowsOptionalFeature -Online -FeatureName MicrosoftWindowsPowerShellV2* |
Select-Object FeatureName, State
Disable-WindowsOptionalFeature -Online -FeatureName MicrosoftWindowsPowerShellV2Root -NoRestart
Beachten Sie: Haben Sie PowerShell 7 (pwsh) ausgerollt, unterscheiden sich sowohl die Konfigurationsschlüssel als auch das Zielprotokoll von 5.1 (die Richtlinie liegt unter PowerShellCore, die Protokolle gehen nach PowerShellCore/Operational). In einer Umgebung, in der beide genutzt werden, wenden Sie Konfiguration, Protokollgrößen-Anpassung und Untersuchungsabfragen auf beide an. Zur Koexistenz der Versionen siehe „Die Unterschiede zwischen Windows PowerShell 5.1 und PowerShell 7“.
5. Die Ausführungsrichtlinie nicht falsch einordnen
Stellen wir es noch einmal ausdrücklich klar: Die Ausführungsrichtlinie ist keine Sicherheitsgrenze. Die offizielle Dokumentation besagt, dass sie eine Sicherheitsfunktion ist, um Benutzer davon abzuhalten, unbeabsichtigt ein Skript auszuführen, und keine Maßnahme, die böswilliges Handeln verhindert.4
Das heißt nicht, dass sie wertlos ist. Signierung hat einen eigenständigen Wert: „Sie können bestätigen, dass ein verteiltes Modul nicht manipuliert wurde“ (siehe „PowerShell-Module intern verteilen und aktualisieren“). Entscheidend ist, ihre Rolle korrekt zu verstehen und entsprechend einzusetzen; die gefährlichste Annahme ist „wir haben AllSigned gesetzt, also sind wir sicher“.
6. Sprachmodi — gemeinsam mit Anwendungssteuerung einsetzen
Eine PowerShell-Sitzung besitzt einen Sprachmodus, der die verfügbaren Sprachelemente einschränkt.5
| Modus | Was verfügbar ist |
|---|---|
| FullLanguage | Alles (Standard) |
| ConstrainedLanguage | Nur genehmigte Typen. Aufrufe beliebiger .NET-Typen und Ähnliches sind eingeschränkt |
| RestrictedLanguage | Befehle können ausgeführt werden, Skriptblöcke jedoch nicht |
| NoLanguage | Nur Befehlsausführung (wird von APIs verwendet) |
Den aktuellen Modus prüfen Sie wie folgt.
$ExecutionContext.SessionState.LanguageMode
Entscheidend ist, wie er gesetzt wird. Der eingeschränkte Sprachmodus funktioniert dadurch, dass PowerShell automatisch dorthin wechselt, wenn Sie allowlist-basierte Anwendungssteuerung mit WDAC (Windows Defender Application Control) oder AppLocker konfiguriert haben.5 Eine manuelle Einstellung über Umgebungsvariablen und Ähnliches lässt sich leicht umgehen und wirkt nicht als Sicherheitsfunktion. Machen Sie sich klar, dass allein die Einschränkung des Sprachmodus ohne Einführung von Anwendungssteuerung kaum etwas für den Aufwand zurückgibt.
7. JEA — „Nur die tatsächlich benötigten Vorgänge“ delegieren
Was den realen Schaden in den meisten Fällen bestimmt, ist die Breite der Berechtigungen. Wo „der Helpdesk Administratorrechte besitzt“ oder „alle im Betrieb in Domain Admins sind“, wird die Kompromittierung eines einzelnen Rechners zur Kompromittierung des gesamten Unternehmens.
JEA (Just Enough Administration) ist ein Mechanismus, um bestimmte Vorgänge zu delegieren, ohne Administratorrechte zu übergeben.6 Es passt exakt zu Anforderungen wie „lasst den Helpdesk den Anwendungsdienst neu starten, und nichts weiter“.
Schritt 1: Die erlaubten Vorgänge in einer Rollenfähigkeitsdatei (.psrc) definieren
Eine Rollenfähigkeitsdatei muss im Ordner RoleCapabilities eines PowerShell-Moduls abgelegt werden. Das bloße Anlegen des Ordners macht ihn noch nicht als Modul erkennbar, und der Name lässt sich nicht über die weiter unten beschriebenen RoleDefinitions auflösen. Legen Sie deshalb zuerst das umschließende Modul an (einen Ordner mit einem Manifest).6
# Das Modul anlegen, das die Rollenfähigkeit aufnehmen wird (ein Manifest ist erforderlich)
$moduleRoot = 'C:\Program Files\WindowsPowerShell\Modules\KsJea'
$null = New-Item -Path "$moduleRoot\RoleCapabilities" -ItemType Directory -Force
# Ein Modulordner benötigt mindestens eine Datei mit demselben Namen wie der Ordner
$null = New-Item -Path "$moduleRoot\KsJea.psm1" -ItemType File -Force
New-ModuleManifest -Path "$moduleRoot\KsJea.psd1" -RootModule 'KsJea.psm1'
# Eine Grundgerüst-Rollenfähigkeitsdatei anlegen (der Dateiname wird zum Rollennamen).
# Rollennamen werden allein nach dem Namen über alle Module auf PSModulePath aufgelöst,
# ein generischer Name wie 'HelpDesk' kann daher mit der .psrc eines anderen Moduls kollidieren.
# Bei einer Kollision ist nicht garantiert, welche gewählt wird, und es können ungewollte Berechtigungen entstehen.
# Verwenden Sie einen eindeutigen Namen mit dem Präfix Ihrer Organisation
New-PSRoleCapabilityFile -Path "$moduleRoot\RoleCapabilities\KsHelpDesk.psrc"
# Prüfen, ob es als Modul sichtbar ist
Get-Module -Name KsJea -ListAvailable
# KsHelpDesk.psrc (Auszug) — deklarieren, was erlaubt ist, und wie weit
@{
GUID = '....'
# Nur lesende Befehle können unverändert freigegeben werden
VisibleCmdlets = @(
'Get-Service',
'Get-EventLog'
)
# Restart-Service ändert den Zustand, deshalb bewusst nicht in VisibleCmdlets aufnehmen (siehe unten)
# VisibleFunctions grenzt nur ein, „welche bereits in die Sitzung geladenen Funktionen“ sichtbar sind;
# es definiert keine Funktionen. Für eigene Funktionen den Rumpf in FunctionDefinitions
# schreiben und den Namen zusätzlich in VisibleFunctions aufführen (beides ist nötig)
VisibleFunctions = @('Get-KsAppStatus', 'Restart-KsAppService')
FunctionDefinitions = @(
@{
Name = 'Get-KsAppStatus'
ScriptBlock = {
# Der Rumpf einer Funktion läuft im Standard-Sprachmodus und unterliegt daher nicht den Einschränkungen von JEA.
# Niemals Benutzereingaben ungeprüft an einen gefährlichen Befehl weiterreichen
Get-Service -Name 'KsAppService' |
Microsoft.PowerShell.Utility\Select-Object Name, Status, StartType
}
},
@{
# Den Neustart als Funktion freigeben, die ihr Ziel nur über ein Argument entgegennehmen kann
Name = 'Restart-KsAppService'
ScriptBlock = {
param(
[Parameter(Mandatory)]
[ValidateSet('KsAppService', 'Spooler')]
[string] $Name
)
Microsoft.PowerShell.Management\Restart-Service -Name $Name
}
}
)
VisibleExternalCommands = @()
}
Allein ValidateSet bei VisibleCmdlets schränkt einen zustandsändernden Befehl nicht sicher ein. Über Parameters und ValidateSet ausgedrückte Einschränkungen werden nur ausgewertet, wenn dieser Parameter tatsächlich gebunden wird. Restart-Service kann einen ServiceController aus der Pipeline entgegennehmen — schreibt jemand also
Get-Service WinRM | Restart-Service
wird -Name nie gebunden, und ValidateSet wird vollständig umgangen. An einem Endpunkt, von dem Sie glaubten, er könne „nur KsAppService und Spooler neu starten“, lässt sich in Wirklichkeit jeder Dienst neu starten.
Dasselbe passiert mit einem anderen Parametersatz. Auch wenn Sie für LogName bei Get-WinEvent ein ValidateSet anfügen, bleibt bei
Get-WinEvent -ProviderName Microsoft-Windows-Security-Auditing -MaxEvents 1
LogName ungebunden, und die Einschränkung wirkt nicht. Da eine JEA-Sitzung als virtueller Administrator läuft, wird in diesem Fall sogar das Security-Protokoll lesbar.
Deshalb hält das obige Beispiel Restart-Service aus VisibleCmdlets heraus und gibt nur eine Wrapper-Funktion frei, die ihr Ziel über ein Argument entgegennehmen kann (Restart-KsAppService). Ist der einzige Eingabepfad ein Argument, gibt es keine Möglichkeit, das zu umgehen.
Einschränkungen über Parameters und ValidateSet greifen nur, „wenn dieser Parameter gebunden wird“. Bei Befehlen, bei denen sich die Bindung über Pipeline-Eingabe oder einen anderen Parametersatz vermeiden lässt, ist die Einschränkung selbst wirkungslos. Nehmen Sie es als Regel: Befehle, deren Argumente Sie einschränken möchten, sollten in eine Wrapper-Funktion verpackt werden.
Hier gibt es zwei leicht zu übersehende Verhaltensweisen. Erstens erzeugt VisibleFunctions keine Funktionen. Eine Funktion, deren Name nur aufgeführt wird, existiert in der Sitzung nicht, und Benutzer sehen „kein solcher Befehl“. Definieren Sie eigene Funktionen in FunctionDefinitions und führen Sie sie zusätzlich in VisibleFunctions auf.7 Wächst die Anzahl, lässt es sich leichter verwalten, sie in ein Skriptmodul auszulagern und dessen Funktionen über VisibleFunctions freizugeben.
Zweitens unterliegt der Rumpf einer Funktion nicht den Einschränkungen von JEA.7 Möchten Sie einen von JEA ersetzten, eingeschränkten Befehl wie Select-Object mit seinem ursprünglichen Verhalten nutzen, rufen Sie ihn wie oben vollqualifiziert als Microsoft.PowerShell.Utility\Select-Object auf. Umgekehrt bedeutet das, innerhalb einer Funktion ist alles möglich — vermeiden Sie deshalb unbedingt Code, der Benutzereingaben an Invoke-Expression weiterreicht.
Schritt 2: In einer Sitzungskonfigurationsdatei (.pssc) festlegen, wer welche Rolle erhält
# SessionType: eingeschränkter Remoteserver (standardmäßig NoLanguage)
# RunAsVirtualAccount: als virtuelles Administratorkonto ausführen
# TranscriptDirectory: aufzeichnen, was ausgeführt wird
$pssc = @{
Path = '.\KsHelpDesk.pssc'
SessionType = 'RestrictedRemoteServer'
RunAsVirtualAccount = $true
TranscriptDirectory = 'C:\JeaTranscripts'
RoleDefinitions = @{ 'EXAMPLE\HelpDesk' = @{ RoleCapabilities = 'KsHelpDesk' } }
}
New-PSSessionConfigurationFile @pssc
Schritt 3: Registrieren
Register-PSSessionConfiguration -Name 'KsHelpDesk' -Path .\KsHelpDesk.pssc -Force
Benutzer verbinden sich wie folgt.
Enter-PSSession -ComputerName 'appsrv01' -ConfigurationName 'KsHelpDesk'
# Nur erlaubte Befehle stehen zur Verfügung. Auch Restart-Service nur für die festgelegten Dienste
Zu JEA gibt es drei zentrale Punkte.6
- Benutzer besitzen keine Administratorrechte. Die Ausführung erfolgt über die Seite des virtuellen Kontos
- Die Sitzung ist als eingeschränkter Remoteserver konfiguriert. Der Sprachmodus ist standardmäßig eingeschränkt, sodass sich kein beliebiger Code ausführen lässt
- Transkripte zeichnen auf, was ausgeführt wurde. So lässt sich prüfen, wer was getan hat
Wie oben erwähnt, muss die Rollenfähigkeitsdatei im RoleCapabilities-Ordner eines Moduls liegen, und dieses Modul muss über $env:PSModulePath auffindbar sein. Lässt sich ein in RoleDefinitions angegebener Rollenname nicht auflösen, prüfen Sie zunächst mit Get-Module -ListAvailable, ob das Modul sichtbar ist.6
Die Bereitstellung setzt voraus, dass Remote-Ausführung konfiguriert ist (siehe „Einstieg in PowerShell Remoting (WinRM)“).
8. Praktische Checkliste
| Punkt | Priorität | Status |
|---|---|---|
| Script Block Logging (4104) aktiviert | Hoch | Unternehmensweit per GPO ausrollen18 |
| Größen der PowerShell-bezogenen Protokolle erweitert | Hoch | Bei Standardwerten innerhalb von Tagen verschwunden |
| Transkription aktiviert und auf einer nur beschreibbaren Freigabe zusammengeführt | Hoch | Nicht lokal auf dem Rechner belassen1 |
| PowerShell-2.0-Engine deaktiviert | Hoch | Ein Umgehungsweg um Protokollierung und AMSI3 |
| Antivirenprodukt unterstützt AMSI | Hoch | Standardmäßig aktiviert2 |
| Ausführungsrichtlinie nicht mit einer Sicherheitsgrenze verwechselt | Mittel | Signierung hat einen anderen Wert4 |
| Umfang der vergebenen Administratorrechte überprüft | Hoch | Die Breite der Berechtigungen bestimmt den Schadensradius |
| Routineaufgaben mit JEA delegiert | Mittel | Reduziert Administratorrechte direkt6 |
| WDAC/AppLocker in Betracht gezogen | Mittel | Die Einschränkung des Sprachmodus geht damit einher5 |
| Protokollierungskonfiguration auch auf der PowerShell-7-Seite ausgerollt | Mittel | Die Einstellungen unterscheiden sich zwischen 5.1 und 7 |
9. Zusammenfassung
- Ein Verbot von PowerShell hat wenig Wirkung und stoppt den Betrieb. Die Strategie sollte „Sichtbarkeit und Einschränkung“ lauten.
- Oberste Priorität hat die Aktivierung von Script Block Logging (4104). Selbst verschleierter Code wird in expandierter Form aufgezeichnet. Erledigen Sie dies zusammen mit der Erweiterung der Protokollgröße.
- Bei der Transkription liegt der entscheidende Punkt in der Zusammenführung auf einer Freigabe, von der Benutzer nicht löschen können.
- Deaktivieren Sie die PowerShell-2.0-Engine, um keinen Weg offenzulassen, auf dem weder Protokollierung noch AMSI greifen.
- Die Ausführungsrichtlinie ist keine Sicherheitsgrenze. Signierung hat Wert als Manipulationserkennung, machen Sie sie aber nicht zum Kern Ihrer Verteidigung.
- Die Breite der Berechtigungen bestimmt die Breite des Schadens. Delegieren Sie mit JEA „nur die tatsächlich benötigten Vorgänge“, und Sie können den Betrieb aufrechterhalten, ohne Administratorrechte zu vergeben.
Beispielcode herunterladen
Der in diesem Artikel behandelte Code wird als direkt lauffähiges Paket bereitgestellt. Er umfasst das Aktivieren der Protokollierungseinstellungen und das Anlegen des JEA-Endpunkts.
Beispielcode herunterladen (zip)
Da die Beispiele zu diesem Artikel von Windows und einem Mandanten abhängen, wurden sie nicht durch Ausführung verifiziert. Die Syntaxanalyse und die statische Analyse mit PSScriptAnalyzer wurden für jede Datei durchgeführt, prüfen Sie das Verhalten aber unbedingt auf Ihrem eigenen Testrechner.
# Syntaxanalyse + statische Analyse (läuft auch auf Nicht-Windows-Plattformen)
./Invoke-SampleTests.ps1
Die Konfigurationswerte (Pfade, Servernamen, Mandanten-IDs und Ähnliches) sind Beispiele. Führen Sie sie nicht unverändert gegen die Produktivumgebung aus — passen Sie sie an Ihre eigene Umgebung an.
Verwandte Artikel
- PowerShell-Ausführungsrichtlinie und Skriptsignierung — Ein praktischer Leitfaden, um vom „Übertünchen mit Bypass“ wegzukommen
- Ereignisprotokolle mit Get-WinEvent praxisnah untersuchen — Die Geschwindigkeit der Filterung entscheidet über die Dauer der Untersuchung
- Einstieg in PowerShell Remoting (WinRM) — Mehrere Windows-Rechner gleichzeitig verwalten
- Anmeldeinformationen in PowerShell sicher handhaben — Klartext-Passwörter aus Ihren Skripten verbannen
- Eine Mindest-Sicherheitscheckliste für die Windows-App-Entwicklung
- Die 10 größten Bedrohungen für die Informationssicherheit 2026 — Wie das Ranking zu lesen ist und wovor sich KMU tatsächlich schützen sollten
Verwandte Beratungsleistungen
KomuraSoft LLC übernimmt die Überprüfung der Sicherheitskonfiguration von Windows-Betriebsumgebungen, das betriebliche Design einschließlich der Delegation von Berechtigungen (JEA) sowie die Beratung zum Aufbau und zur Nutzung von Audit-Protokollen.
- Technische Beratung und Design-Review
- Fehleruntersuchung und Ursachenanalyse
- Änderung und Wartung bestehender Windows-Software
- Kontakt
Referenzlinks
-
Microsoft Learn, about_Logging_Windows. Zu den drei Arten der Protokollierung (Modulprotokollierung, Script Block Logging und Transkription), zur Aktivierung über Gruppenrichtlinie und Registrierung (unter HKLM\SOFTWARE\Policies\Microsoft\Windows\PowerShell), dazu, dass Script Block Logging entschleierten Code als Ereignis-ID 4104 aufzeichnet, dass Modulprotokollierung als Ereignis-ID 4103 aufgezeichnet wird, sowie zu den Einstellungen OutputDirectory und EnableInvocationHeader der Transkription. ↩ ↩2 ↩3 ↩4 ↩5 ↩6 ↩7 ↩8
-
Microsoft Learn, Antimalware Scan Interface (AMSI). Dazu, dass AMSI ein Mechanismus ist, über den Anwendungen und Dienste Inhalte zur Prüfung an ein beliebiges Antimalware-Produkt übergeben, und dazu, dass Windows-Skript-Engines einschließlich PowerShell damit integriert sind, sodass selbst verschleierte Skripte mit ihrem Inhalt zum Ausführungszeitpunkt geprüft werden können. ↩ ↩2 ↩3
-
Microsoft Learn, Deprecating Windows PowerShell 2.0. Dazu, dass die Engine Windows PowerShell 2.0 veraltet ist und ihre Deaktivierung empfohlen wird, sowie dazu, dass sie als optionales Windows-Feature bereitgestellt wird, das sich aktivieren oder deaktivieren lässt. ↩ ↩2 ↩3
-
Microsoft Learn, about_Execution_Policies. Dazu, dass die Ausführungsrichtlinie keine Sicherheitsgrenze ist, sondern eine Sicherheitsfunktion, um Benutzer davon abzuhalten, unbeabsichtigt Skripte auszuführen, sowie zum Vorhandensein mehrerer Umgehungswege. ↩ ↩2 ↩3
-
Microsoft Learn, about_Language_Modes. Zu den verfügbaren Sprachelementen in FullLanguage, ConstrainedLanguage, RestrictedLanguage und NoLanguage, zur Prüfung des aktuellen Modus über $ExecutionContext.SessionState.LanguageMode, dazu, dass PowerShell im eingeschränkten Sprachmodus läuft, wenn Anwendungssteuerung über WDAC oder AppLocker wirksam ist, sowie dazu, dass die manuelle Konfiguration des Sprachmodus nicht als Sicherheitsfunktion gedacht ist. ↩ ↩2 ↩3 ↩4
-
Microsoft Learn, Just Enough Administration (JEA) Overview. Dazu, dass JEA ein Mechanismus ist, um nur bestimmte administrative Aufgaben zu delegieren, ohne Administratorrechte zu gewähren, zu VisibleCmdlets in einer Rollenfähigkeitsdatei (.psrc) und Einschränkungen über Parameters und ValidateSet, zu RestrictedRemoteServer, RunAsVirtualAccount, TranscriptDirectory und RoleDefinitions in einer Sitzungskonfigurationsdatei (.pssc), zur Registrierung über Register-PSSessionConfiguration sowie dazu, dass der Sprachmodus in einer JEA-Sitzung eingeschränkt ist. Zur Anforderung, Rollenfähigkeitsdateien im RoleCapabilities-Ordner eines PowerShell-Moduls abzulegen (damit es als Modul auffindbar bleibt, und zum Anlegen von Dateien mit New-PSRoleCapabilityFile), siehe JEA Role Capabilities. ↩ ↩2 ↩3 ↩4 ↩5 ↩6
-
Microsoft Learn, JEA Role Capabilities. Dazu, dass eigene Funktionen in FunctionDefinitions definiert und ihre Namen zusätzlich in VisibleFunctions aufgeführt werden müssen („Don’t forget to add the name of your custom functions to the VisibleFunctions field so they can be run by the JEA users.“), dazu, dass der Rumpf einer Funktion (der Skriptblock) im systemseitigen Standard-Sprachmodus läuft und daher nicht den Einschränkungen von JEA unterliegt, zur Notwendigkeit eines vollqualifizierten Namens (Microsoft.PowerShell.Utility\Select-Object), um die ursprüngliche Implementierung eines von JEA ersetzten, eingeschränkten Befehls zu nutzen, zum Vorgehen, Funktionen bei großer Anzahl in ein Skriptmodul auszulagern und über VisibleFunctions freizugeben, sowie dazu, dass der Modulordner eine Datei mit demselben Namen wie der Ordner benötigt. ↩ ↩2
-
Microsoft Learn, Set-ItemProperty. Dazu, dass -Type als dynamischer Parameter hinzugefügt wird, wenn der Registrierungsanbieter verwendet wird, wodurch sich der Datentyp eines Registrierungswerts (String / ExpandString / Binary / DWord / MultiString / QWord und weitere) angeben lässt. Einschließlich der Tatsache, dass der Wert angelegt wird, falls er nicht existiert. ↩
Verwandte Artikel
Aktuelle Artikel mit denselben Schlagwörtern führen zu verwandten Themen weiter.
PC-Kitting mit winget + PowerShell automatisieren — Aus dem Handbuch ein ausführbares Skript machen
Wie Sie die Einrichtung von PCs für neue Mitarbeitende reproduzierbar gestalten. Behandelt die Installation von Anwendungen mit winget so...
Ereignisprotokolle mit Get-WinEvent praxisnah untersuchen — Die Geschwindigkeit der Filterung entscheidet über die Dauer der Untersuchung
Wie Sie die Untersuchung von Windows-Ereignisprotokollen mit PowerShell effizient gestalten. Behandelt, warum die Filterung mit Where-Obj...
Schluss mit Write-Host — PowerShells Ausgabeströme und Log-Design
Wie Sie zwischen den sechs Ausgabeströmen von PowerShell wählen, welche Probleme Write-Host mit sich bringt und wo es tatsächlich hingehö...
Zugangsdaten in PowerShell sicher handhaben — Klartext-Passwörter aus Ihren Skripten verbannen
Ein praktischer Leitfaden, um Klartext-Passwörter aus PowerShell-Skripten zu entfernen und sicher zu speichern: was SecureString wirklich...
Mit PowerShell einen Dateiserver bestandsaufnehmen ── Kapazitätsanalyse und Zugriffsrechte-(ACL)-Audit
Ein praktisches Vorgehen zur Bestandsaufnahme eines Dateiservers mit PowerShell. Behandelt Kapazitätsanalyse und das Protokollieren von Z...
Verwandte Themen
Diese Seiten ordnen den Artikel in einen größeren Leistungs- und Entscheidungskontext ein.
Technische Windows-Themen
Portal zu Windows-Entwicklung, Fehleranalyse und der Nutzung bestehender Assets.
Leistungen zu diesem Thema
Dieser Artikel ist direkt mit den folgenden Leistungen verbunden.
Windows-App-Entwicklung
Geschäftsanwendungen, Geräteintegration und Kommunikationstools von den Anforderungen bis zur Umsetzung.
Häufige Fragen
Fragen, die in Beratungen zu diesem Artikelthema häufig gestellt werden.
- Sollten wir PowerShell als Sicherheitsmaßnahme unternehmensweit verbieten?
- Wir raten davon ab: Die tatsächliche Wirkung ist gering, die Nebenwirkungen sind groß. PowerShell ist selbst die Verwaltungsgrundlage von Windows und im Kern nichts anderes als eine Sammlung von Fähigkeiten auf Basis von .NET. Wird die ausführbare Datei blockiert, bleiben dieselben APIs über andere Wege weiterhin aufrufbar — für einen Angreifer ist das kaum ein Hindernis, während legitime Administration und Automatisierung zuverlässig gestoppt werden. Die realistische Strategie lautet nicht Verbot, sondern Sichtbarkeit und Einschränkung. Zeichnen Sie mit Script Block Logging auf, was ausgeführt wurde, deaktivieren Sie die alte Engine-Version und schränken Sie, wo nötig, mit Sprachmodi oder JEA ein, was ausgeführt werden darf.
- Wenn wir Script Block Logging aktivieren, ertrinken wir dann nicht in Protokollen?
- Das Volumen nimmt tatsächlich zu, aktivieren Sie es deshalb zusammen mit einer Überprüfung Ihrer Protokollgrößen-Einstellungen. Belassen Sie die Maximalgröße des Protokolls Microsoft-Windows-PowerShell/Operational auf dem Standardwert, läuft es in kurzer Zeit über, und genau die Einträge, die Sie im Ernstfall brauchen, sind dann verschwunden. Betrieblich sollten Sie eine großzügige Protokollgröße vorsehen und die Daten bei Bedarf in einem SIEM oder über Event Forwarding zusammenführen. Es gibt zudem eine Einstellung, die detailliertere Start-/Stopp-Ereignisse einzelner Aufrufe aufzeichnet, deren Ausgabemenge jedoch sehr hoch ist — im Normalfall sollten Sie nur das standardmäßige Script Block Logging aktivieren.
- Zählt das Setzen der Ausführungsrichtlinie auf AllSigned als Sicherheitsmaßnahme?
- Die Ausführungsrichtlinie ist keine Sicherheitsgrenze. Die offizielle Dokumentation stellt ausdrücklich klar, dass sie ein Mechanismus ist, um Benutzer davon abzuhalten, unbeabsichtigt gefährliche Skripte auszuführen, und keine Maßnahme gegen böswilliges Handeln — da mehrere Umgehungswege existieren. Signierung hat einen eigenständigen Wert, nämlich die Integrität des Verteilten überprüfen zu können; der Kern Ihrer Verteidigung sollte jedoch aus Sichtbarkeit durch Protokolle, Prüfung durch AMSI und Einschränkung von Berechtigungen durch Sprachmodi und JEA bestehen.
- Ist es in Ordnung, den ConstrainedLanguage-Modus manuell zu setzen?
- Eine manuelle Einstellung über Umgebungsvariablen und Ähnliches wird nicht empfohlen. Sie lässt sich leicht umgehen und wirkt nicht als Sicherheitsfunktion. Der eingeschränkte Sprachmodus ist so konzipiert, dass er als Folge der Konfiguration von Anwendungssteuerung mit WDAC (Windows Defender Application Control) oder AppLocker zum Einsatz kommt, wobei PowerShell dann automatisch in diesen Modus wechselt. Nur den Sprachmodus einzuschränken, ohne Anwendungssteuerung einzuführen, ergibt keinen wirksamen Schutz.
- Ich möchte einem Helpdesk-Mitarbeiter erlauben, genau einen bestimmten Dienst auf einem Server neu zu starten, und sonst nichts.
- Genau dafür ist JEA (Just Enough Administration) der passende Mechanismus. In einer Rollenfähigkeitsdatei legen Sie fest, „nur diesen Wert, dieses Parameters, dieses Befehls“ zu erlauben, und registrieren dies als Sitzungskonfiguration. Benutzer können dann nur die erlaubten Vorgänge ausführen, über ein virtuelles Konto, ohne selbst Administratorrechte zu besitzen. Die Sitzung ist als eingeschränkter Remoteserver konfiguriert, und standardmäßig ist auch der Sprachmodus eingeschränkt, sodass kein Raum für die Ausführung beliebigen Codes bleibt. Was ausgeführt wird, lässt sich als Transkript aufzeichnen.
Autorenprofil
Profilseite des Artikelautors.
Go Komura
Geschäftsführer von KomuraSoft LLC
Spezialisiert auf Windows-Softwareentwicklung, technische Beratung und Fehleranalyse, insbesondere bei bestehenden Systemen und schwer reproduzierbaren Störungen.