Welche Sicherheitsmaßnahmen stehen dem Administrator zur Verfügung, um die PowerShell produktiv abzusichern und trotzdem administrative Aufgaben an Nicht-Administratoren zu delegieren (JEA)? Wie können verdächtige und unerwünschte Aktivitäten protokolliert werden (ScriptBlockLogging)? Wie sollten die Ausführungsrichtlinien eingestellt sein und was bedeutet das für den Betrieb? Solche und noch weitere Fragen werden hier geklärt, um die Sicherheit an der PowerShell zu erhöhen. Von https://attilakrick.com
PowerShell Sicherheit in 6 Schritten produktiv absichern
1. C12_Sicherheit-an-PowerShell.md 7/11/2020
1 / 18
PowerShell in 7 Schritten produktiv absichern
Powered by
_ _ _ _ _ _ _
| | | | (_) | | | (_) | |
__ _| |_| |_ _| | __ _| | ___ __ _ ___| | __ ___ ___ _ __ ___
/ _` | __| __| | |/ _` | |/ / '__| |/ __| |/ / / __/ _ | '_ ` _
| (_| | |_| |_| | | (_| | <| | | | (__| < | (_| (_) | | | | | |
__,_|__|__|_|_|__,_|_|__| |_|___|_|_(_)______/|_| |_| |_|
---------------------- HTTPS://ATTILAKRICK.COM ---------------------
PowerShell Sicherheit - Die Keywords
Zusammenfassungen
Welche Sicherheitsmaßnahmen stehen dem Administrator zur Verfügung, um die PowerShell produktiv
abzusichern und trotzdem administrative Aufgaben an Nicht-Administratoren zu delegieren (Just Enough
Administration, JEA)? Wie können verdächtige und unerwünschte Aktivitäten protokolliert werden
(ScriptBlockLogging)? Wie sollten die Ausführungsrichtlinien eingestellt sein und was bedeutet das für den
Betrieb? Solche und noch weitere Fragen werden hier geklärt, um die Sicherheit an der PowerShell zu
erhöhen.
Schlagwörter
Sicherheit, ExecutionPolicy, ScriptBlockLogging, LanguageMode, JEA
Version
2020.07.02
Permalink
https://attilakrick.com/powershell/powershell-sicherheit/
Einführung
Die PowerShell ist ein Bestandteil des Betriebssystems. Daher sorgt ein generelles Blockieren nur für
scheinbare PowerShell Sicherheit. Den besten Schutz versprechen die Schutz- und Protokollierungs-
Mechanismen von PowerShell selbst.
In diesem Artikel beleuchte wir das Thema PowerShell Sicherheit aus dem Blickwinkel eines Administrators.
Wie PowerShell produktiv abgesichert wird, um trotzdem administrative Aufgaben an Nicht-Administratoren
zu delegieren (Just Enough Administration). Auch geht es darum verdächtige und unerwünschte Aktivitäten zu
protokollieren (ScriptBlockLogging).
2. C12_Sicherheit-an-PowerShell.md 7/11/2020
2 / 18
TIPP - Neben der administrativen Absicherung, um die PowerShell Sicherheit zu erhöhen, sollten Sie
auch mit sensiblen Daten wie Zugangsdaten, Geheimnisse und Zugangsbeschränkungen entsprechend
umgehen und schützen. Wie Sie das in PowerShell realisieren, finden Sie im Artikel "Mit Sicherheit in
der PowerShell umgehen".
INTERESSANT - Eine gründliche Analyse der Sicherheittechnologie zwischen verfügbaren Shells und
Skriptsprachen finden Sie in dem Artikel Ein Vergleich der Sicherheit von Shell und Skriptsprache.
Altlasten entfernen erhöht die PowerShell Sicherheit
Unbedingt sollten Sie PowerShell 2.0 deinstallieren. Mit dieser alten Shell-Version lassen sich alle
wesentlichen Restriktionen für PowerShell unterlaufen. Das optionale Feature ist vorinstalliert und kann aber
ab Windows 8.1 und Server 2012 deinstalliert werden.
Statische Strings erhöht die Sicherheit
Grundsätzlich immer die einfachen Hochkommas ' verwenden. Es seiden man verwendet Variable im String,
erst dann die doppelten Hochkommas " verwenden. Das erhöht die Sicherheit da die Gefahr von String-
Injection minimiert wird.
# ! FALSCH
$Ort = "Würzburg"
# RICHTIG
$Ort = 'Würzburg'
$s = 'Hallo $Ort!'
# vs.
$s = "Hallo $Ort!"
Ausführungsrichtlinien korrekt konfigurieren
Die Ausführungsrichtlinie ist ein PowerShell Sicherheit-Funktion, die steuert unter welchen Bedingungen
Konfigurations- und Skript-Dateien ausgeführt werden. Die Ausführungsrichtlinien schränken
Benutzeraktionen nicht ein. Stattdessen helfen die Ausführungsrichtlinien Benutzern, dass sie nicht
unbeabsichtigt gegen diese Regeln verstoßen.
WICHTIG - Das Verändern der Ausführungsrichtlinien stellt NUR einen Schutz vor dem unbedarften
Ausführen von Skripts dar - MEHR NICHT!
# READ betroffene About-Seiten:
Get-Help -Name 'about_Execution_Policy' -ShowWindow
# ? Wie ist der aktuelle Status der Ausführungsrichtlinien:
Get-ExecutionPolicy -List
# ? Wie ist die Ausführungsrichtlinie für den aktuellen Script-Host eingestellt:
$env:PSExecutionPolicyPreference
3. C12_Sicherheit-an-PowerShell.md 7/11/2020
3 / 18
Empfohlene Einstellung für Client und Server: Alle ausführbaren Dateien müssen mit einem x.509-Zertifikat
signiert sein.
Set-ExecutionPolicy -ExecutionPolicy 'AllSigned' -Force
Empfohlene Einstellung für Test- und Entwicklungs-Systeme: Alle ausführbaren Dateien die Remote (z.B.
per Download oder UNC-Pfad, etc.) auf den PC gelangt sind, müssen mit einem X.509-Zertifikat signiert sein.
Diese Dateien werden an einem 'Download-Marker' identifiziert. Dieser kann per Cmdlet Unblock-File
wieder entfernt werden.
Set-ExecutionPolicy -ExecutionPolicy 'RemoteSigned' -Force
Für das automatische Ausführen von signierten Skripten müssen folgende Voraussetzungen erfüllt sein.
1. Das X.509-Zertifikat muss von einer "Vertrauenswürdigen Stammzertifizierungsstelle" (Root) abstammt
ODER es ist selbst in Root abgelegt!
2. Das X.509-Zertifikat muss im Zertifikatspeicher für "Vertrauenswürdige Herausgeber"
(TrustPublisher) enthalten ist.
Ausführungsrichtlinien per GPO steuern: Die Ausführungsrichtlinien können komfortable per GPO
eingestellt werden. Diese wiederum manipulieren folgende Registry-Schlüssel.
Get-ItemPropertyValue -Path
'Registry::HKEY_LOCAL_MACHINESOFTWAREMicrosoftPowerShell1ShellIdsMicrosoft.P
owerShell' -Name 'ExecutionPolicy'
Get-ItemPropertyValue -Path
'Registry::HKEY_LOCAL_MACHINESOFTWAREMicrosoftPowerShell1ShellIdsScriptedDia
gnostics' -Name 'ExecutionPolicy'
Get-ItemPropertyValue -Path
''Registry::HKEY_CURRENT_USERSoftwareMicrosoftPowerShell1ShellIdsMicrosoft.P
owerShell -Name 'ExecutionPolicy'
Skript benötigt erhöhte Admin-Rechte
Im administrativen Umfeld ist nötig, dass Skripte mit erhöhte Admin-Rechte laufen. Zum Skript-Beginn kann
man überprüfen ob die Admin-Rechte vorhanden sind. Sollte dies nicht der Fall sein so könnte das Skript zu
beginn abbrechen, anstatt fehlerhaft in der Mitte auszusteigen.
$IsElevatedAdminRights = ([Security.Principal.WindowsPrincipal]
[Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.W
indowsBuiltInRole]'Administrator')
if(-not $IsElevatedAdminRights) {
5. C12_Sicherheit-an-PowerShell.md 7/11/2020
5 / 18
Import-Certificate -FilePath 'C:TempSuperman.cer' -CertStoreLocation
'Cert:LocalMachineRoot'
Import-PfxCertificate -FilePath 'C:TempSuperman.pfx' -CertStoreLocation
'Cert:CurrentUserMy' -Password (Read-Host -Prompt 'PFX-Password for Superman' -
AsSecureString)
# ! Zertifikat aus dem Dateisystem lesen und auf Verwendungszweck testen:
Get-PfxData -Password (Read-Host -Prompt 'PFX-Password for Superman' -
AsSecureString) -FilePath 'C:TempSuperman.pfx' | Format-List -Property '*'
$test = Get-PfxCertificate -FilePath 'C:TempSuperman.pfx'
Test-Certificate -Cert $test -Policy 'SSL' | Write-Warning
Test-Certificate -Cert $test -EKU '1.3.6.1.5.5.7.3.1' | Write-Warning # = Server
Authentication
# ! Zertifikat aus dem Cert-Speicher lesen und auf Verwendungszweck testen:
Get-ChildItem -Path 'Cert:CurrentUserMy' | Where-Object -Property 'Subject' -
CLike -Value 'CN=_Superman (Doctor S. Man), E=s.man@krypton.universe' | Test-
Certificate -Policy 'SSL' | Write-Warning
Get-ChildItem -Path 'Cert:LocalMachineRoot' | Where-Object -Property 'Subject' -
CLike -Value 'CN=_Superman (Doctor S. Man), E=s.man@krypton.universe' | Test-
Certificate -EKU '1.3.6.1.5.5.7.3.1' | Write-Warning
# TODO Aufräumen:
Remove-Item -Path 'C:TempSuperman.*' -Force
Get-ChildItem -Path 'Cert:LocalMachine', 'Cert:CurrentUser' -Recurse | Where-
Object -Property 'Subject' -CLike -Value 'CN=_Superman (Doctor S. Man),
E=s.man@krypton.universe' | Remove-Item -Force
PowerShell Script-Dateien signieren
Warum sollte man signieren:
1. Eine Signatur schützt ein Skript (.PS1, .PSM1, .PS1XML, ...) vor Manipulation und erhöht so die
PowerShell Sicherheit!
2. Der Signierer bestätigt mit seiner Signatur den endgültigen Status des Skriptes!
3. Dritte können erkennen wer dieses Skript signiert / erstellt hat.
PowerShell kann über die Ausführungsrichtlinien so konfiguriert werden (AllSigned), dass nur Skripte
ausgeführt werden, wenn folgende Voraussetzungen erfüllt sind:
1. Die Skriptdatei wurde mit einem X.509-Zertifikat signiert!
2. Die signierte Datei wurde anschließend nicht manipuliert!
3. Das Signierer-Zertifikat stamm von einer "Vertrauenswürdigen Stammzertifizierungsstelle" (Root) ab
ODER es ist selbst in Root abgelegt worden!
6. C12_Sicherheit-an-PowerShell.md 7/11/2020
6 / 18
4. Signierer-Zertifikat wurde zusätzlich im Zertifikatspeicher für "Vertrauenswürdige Herausgeber"
(TrustPublisher) abgelegt!
Zum Beispiel an einer einfachen Umsetzung über ein selbstsigniertes Zertifikat:
# ! 1. Testumgebung vorbereiten
# Ausführungsrichtlinien auf AllSigned setzen
Set-ExecutionPolicy -ExecutionPolicy 'AllSigned' -Scope 'Process' -Force
Set-ExecutionPolicy -ExecutionPolicy 'AllSigned' -Scope 'CurrentUser' -Force
Set-ExecutionPolicy -ExecutionPolicy 'AllSigned' -Scope 'LocalMachine' -Force
# PKI Modul importieren
Import-Module -Name 'PKI' # Windows PowerShell
Import-WinModule -Name 'PKI' # bzw. PowerShell 7
# Test-Ordner C:Temp erstellen
New-Item -Path 'C:Temp' -ItemType 'Directory' -Force | Set-Location
# Test-Script erzeugen
'"> > > Execute Code from .PS1-Script! at $(Get-Date) < < <" | Write-Warning' |
Set-Content -Path '.Test.ps1' -Force
# ! 2. Aktuell wird das Ausführen des Skriptes mit einer Fehlermeldung abgebrochen
. '.Test.ps1'
# ! 3. Signierer-Zertifikate erstellen:
$params = @{
Subject = 'CN=_FirstName_LastName (PS Developer),
E=f.lastname@abc.local'
HashAlgorithm = 'SHA512'
KeyExportPolicy =
[Microsoft.CertificateServices.Commands.KeyExportPolicy]::ExportableEncrypted
CertStoreLocation = 'Cert:CurrentUserMy'
Type = [
Microsoft.CertificateServices.Commands.CertificateType]::CodeSigningCert
NotAfter = (Get-Date).AddYears(5)
}
$myPfxCert = New-SelfSignedCertificate @params
# ! 4. Aus dem Signierer-Zertifikat ein öffentliches Zertifikat erstellen:
$myPfxCert | Export-Certificate -FilePath '.PublicSignerCertificate.cer' -Type
'CERT' -Force
# ! 5. Vertrauensstellung einrichten:
# 1. im Zertifikatsspeicher Root abgelegt werden, um dem Zertifikat generell zu
vertrauen
Import-Certificate -FilePath '.PublicSignerCertificate.cer' -CertStoreLocation
'Cert:LocalMachineRoot'
# 2. im Zertifikatsspeicher TrustedPublisher abgelegt werden, um den signierten
7. C12_Sicherheit-an-PowerShell.md 7/11/2020
7 / 18
.PS1-Dateien im Besonderen zu vertrauen
Import-Certificate -FilePath '.PublicSignerCertificate.cer' -CertStoreLocation
'Cert:LocalMachineTrustedPublisher'
# ! 6. Das eigentliche Script signieren:
$params = @{
Certificate = $myPfxCert
HashAlgorithm = 'SHA512'
TimestampServer = 'http://timestamp.globalsign.com/scripts/timstamp.dll'
FilePath = '.Test.ps1'
}
Set-AuthenticodeSignature @params
# ! 7. Signiertes Script testen:
# ? Die digitale Signatur sollte GÜLTIG sein?
Get-AuthenticodeSignature -FilePath '.Test.ps1' | Format-List -Property *
# ? Wird .PS1-Datei nun problemlos ausgeführt?
. '.Test.ps1'
# ! 8. Aufräumen
Set-ExecutionPolicy -ExecutionPolicy 'RemoteSigned' -Scope 'Process' -Force
Set-ExecutionPolicy -ExecutionPolicy 'RemoteSigned' -Scope 'CurrentUser' -Force
Set-ExecutionPolicy -ExecutionPolicy 'RemoteSigned' -Scope 'LocalMachine' -Force
Get-ChildItem -Path 'Cert:CurrentUserMy', 'Cert:LocalMachineRoot',
'Cert:LocalMachineTrustedPublisher' | Where-Object Thumbprint -CEQ
$myPfxCert.Thumbprint | Remove-Item
Get-ChildItem -Path '.Test.ps1', '.PublicSignerCertificate.cer' | Remove-Item
TIPP - Vielleicht besitzen Sie ja schon ein entsprechendes Zertifikat zum Signieren. Lassen Sie sich diese wie
folgt anzeigen.
Get-ChildItem -Path 'Cert:CurrentUserMy' -CodeSigningCert
Einfache Host-Ein-/Ausgabe Protokollierung
Eine einfache Variante, um die PowerShell Sicherheit zu erhöhen, ist das Mitschneiden sämtlicher Aktivitäten
und deren Resultate auf einem PowerShell Host. Hierzu verwenden Sie die Cmdlets Start-Transcript und
Stop-Transcript.
# * 1. Transcript starten:
Start-Transcript -Path "C:TempPsHost.log" -Append -Force
# * 2. Test-Eingabe & -Ausgaben erzeugen:
Get-Process
Read-Host -Prompt "Passwort eingeben" -AsSecureString
# * 3. Transcript stoppen:
8. C12_Sicherheit-an-PowerShell.md 7/11/2020
8 / 18
Stop-Transcript -Verbose
# 4. Log-Datei Anzeigen:
Start-Process -FilePath "C:TempPsHost.log"
Wo und wann Sie Start-Transcript initiieren obliegt Ihnen. Denkbar wäre z.B. einer der Autostartdateien
(profile.ps1).
Aktivitäten mittels ScriptBlockLogging protokollieren
Wenn ScriptBlockLogging aktiviert ist werden sämtliche Befehle zu PowerShell-Vorgängen protokolliert.
Durch den lückenlosen Nachweis sämtlicher PowerShell-Aktivität wir die PowerShell Sicherheit weiter erhöht.
WICHTIG - Bzgl. PowerShell 7: Bevor Ereignisse in das Ereignisprotokoll geschrieben werden können,
muss im Gegensatz zu Linux oder macOS in Windows der Ereignisanbieter registriert sein. Führen Sie
dazu mit erhöhten Berechtigungen folgendes aus.
. "$PsHomeRegisterManifest.ps1"
Get-WinEvent -ListProvider '*powershell*' | Select-Object -Property 'Name'
Permanentes und sicheres Protokollieren sämtlicher Host-Aktivitäten mittels ScriptBlockLogging
aktivieren.
TIPP - ScriptBlockLogging per GPO unter Computerkonfiguration / Administrative Vorlagen
/ Windows-Komponenten / Windows PowerShell / Protokollierung von PowerShell-
Scriptblöcken aktivieren. ACHTUNG - z.Zt. nur für Windows PowerShell, andere Versionen nur per
folgenden Registry-Keys.
# ! Für PowerShell 7 und PowerShell Core:
New-Item -Path
'Registry::HKEY_LOCAL_MACHINESOFTWAREPoliciesMicrosoftPowerShellCore' -Name
'ScriptBlockLogging' -ItemType 'Key' -Force | New-ItemProperty -Name
'EnableScriptBlockLogging' -Value 1 -PropertyType 'DWord' -Force
# ! Für Windows PowerShell:
New-Item -Path
'Registry::HKEY_LOCAL_MACHINESOFTWAREPoliciesMicrosoftWindowsPowerShell' -
Name 'ScriptBlockLogging' -ItemType 'Key' -Force | New-ItemProperty -Name
'EnableScriptBlockLogging' -Value 1 -PropertyType 'DWord' -Force
# ! Für Windows PowerShell 32it:
Registry::HKEY_LOCAL_MACHINESOFTWAREWOW6432NodePoliciesMicrosoftWindowsPower
ShellScriptBlockLogging
# ! Für PowerShell Core 32bit:
Registry::HKEY_LOCAL_MACHINESOFTWAREWOW6432NodePoliciesMicrosoftWindowsPower
ShellCoreScriptBlockLogging
9. C12_Sicherheit-an-PowerShell.md 7/11/2020
9 / 18
Die so protokollierten Aktivitäten können nun wie folgt ausgewertet werden.
# Test-Code der gleich im Protokoll auftaucht:
Get-ChildItem -Path 'C:Temp'
# ! Auswertung:
Get-WinEvent -ListLog '*powershell*'
Get-WinEvent -FilterHashtable @{ LogName='PowerShellCore/Operational' ; Id="4104"
} | Select-Object -Property 'RecordId', 'ProcessId', 'MachineName', 'UserId',
'TimeCreated', 'Message' | Where-Object -Property 'Message' -IMatch -Value 'Get-
ChildItem'
# TODO Aufräumen:
. "$PsHomeRegisterManifest.ps1" -Unregister
Remove-Item -Path
'Registry::HKEY_LOCAL_MACHINESOFTWAREPoliciesMicrosoftPowerShellCoreScriptBlo
ckLogging' -Recurse -Force
Remove-Item -Path
'Registry::HKEY_LOCAL_MACHINESOFTWAREPoliciesMicrosoftWindowsPowerShellScrip
tBlockLogging' -Recurse -Force
TIPP - Um die PowerShell Sicherheit weiter zu erhöhen, sollten sensible Daten im Protokoll geschützt
werden. Dazu verschlüsseln Sie einfach die Logs (s. Protected Event Logging unter Get-Help -Name
'about_logging_windows' -ShowWindow).
Aktivitäten in der PowerShell-Session einschränken (LanguageMode)
Über $ExecutionContext.SessionState.LanguageMode können Sie weiter einschränken welche Cmdlets,
Typen und Interaktionen erlaubt sind, um die PowerShell Sicherheit weiter zu erhöhen.
# ! Zum Beispiel aktivieren per Autostart über eine der folgenden Dateien:
$profile.AllUsersAllHosts
$profile.AllUsersCurrentHost
# ! 1. Keine Anwendungen und Skripte ab jetzt erlauben:
$ExecutionContext.SessionState.Applications.Clear()
$ExecutionContext.SessionState.Scripts.Clear()
# ! 2. Erlaubte Cmdlets festlegen und die restlichen Cmdlets unsichtbar machen:
$allowedCommands = @()
$allowedCommands += "ForEach-Object"
$allowedCommands += "Get-ChildItem"
$allowedCommands += "Get-Command"
$allowedCommands += "Get-Member"
$allowedCommands += "Get-Module"
$allowedCommands += "Out-Default"
$allowedCommands += "Select-Object"
$allowedCommands += "Test-NetConnection"
$allowedCommands += "Where-Object"
10. C12_Sicherheit-an-PowerShell.md 7/11/2020
10 / 18
Get-Command -CommandType "Cmdlet", "Function" | Where-Object -Property Name -
NotIn -Value $allowedCommands | ForEach-Object -Process { $_.Visibility =
"Private" }
# ! 3. Den LanguageMode in den beschränkten Sprachmodus versetzen:
$ExecutionContext.SessionState.LanguageMode = "RestrictedLanguage"
Weitere LanguageMode-Details entnehmen Sie den entsprechenden About-Seiten.
# READ siehe auch:
Get-Help -Name 'about_Language_Modes' -ShowWindow
Get-Help -Name 'about_FullLanguage' -ShowWindow
Get-Help -Name 'about_RestrictedLanguage' -ShowWindow
Get-Help -Name 'about_ConstrainedLanguage' -ShowWindow
Um zu ermitteln in welchem Modi sich die aktuelle Sitzung befindet, können Sie die LanguageMode
Eigenschaft abfragen:
$ExecutionContext.SessionState.LanguageMode
Zu den wichtigsten PowerShell Sicherheits-mechanismen gehört der Constrained Language Mode (CLM) die
mehrere gefährlichen PowerShell-Features deaktiviert und so deren Missbrauch minimiert und die PowerShell
Sicherheit erhöht. Der ConstrainedLanguage-Modus erlaubt alle Cmdlets und alle PowerShell-
Sprachelemente, begrenzt jedoch die zulässigen Typen.
Wenn der LanguageMode auf ConstrainedLanguage steht werden folgende wichtige Funktionen geboten:
Alle Cmdlets in Windows-Modulen und andere von UMCI genehmigte Cmdlets sind voll funktionsfähig
und haben, sofern nicht anders angegeben, vollständigen Zugriff auf Systemressourcen.
Alle in Windows enthaltenen Module können importiert und alle Befehle, die die Module exportieren, in
der Sitzung ausgeführt werden.
Das Cmdlet Add-Type kann signierte Assembly laden, jedoch keinen beliebigen C# -Code oder Win32-
APIs.
Das Cmdlet New-Object kann nur für zulässige Typen verwendet werden (siehe unten).
Die Typkonvertierung ist zulässig, jedoch nur, wenn das Ergebnis ein zulässiger Typ ist.
Cmdlet-Parameter, die Zeichenfolgeneingaben in Typen konvertieren, funktionieren nur, wenn der
resultierende Typ ein zulässiger Typ ist.
Es sind nur folgende COM-Objekte zulässig:
Scripting.Dictionary
Scripting.FileSystemObject
VBScript.RegExp
Die folgenden Typen sind im ConstrainedLanguage-Modus zulässig. Benutzer können Eigenschaften
abrufen, Methoden aufrufen und Objekte in diese Typen konvertieren.
11. C12_Sicherheit-an-PowerShell.md 7/11/2020
11 / 18
[AliasAttribute], [AllowEmptyCollectionAttribute], [AllowEmptyStringAttribute],
[AllowNullAttribute], [Array], [Bool], [byte], [char], [CmdletBindingAttribute], [DateTime],
[decimal], [DirectoryEntry], [DirectorySearcher], [double], [float], [Guid], [Hashtable], [int],
[Int16], [long], [ManagementClass], [ManagementObject], [ManagementObjectSearcher],
[NullString], [OutputTypeAttribute], [ParameterAttribute], [PSCredential],
[PSDefaultValueAttribute], [PSListModifier], [PSObject], [PSPrimitiveDictionary],
[PSReference], [PSTypeNameAttribute], [Regex], [SByte], [string],
[SupportsWildcardsAttribute], [SwitchParameter], [System.Globalization.CultureInfo],
[System.Net.IPAddress], [System.Net.Mail.MailAddress], [System.Numerics.BigInteger],
[System.Security.SecureString], [TimeSpan], [UInt16], [UInt32], [UInt64]
Seit PowerShell 5 wird automatisch erkannt ob in den Constrained Language Mode gewechselt werden
soll. Die PowerShell legt dazu unter $env:TEMP temporär ein Script an und versucht dieses auszuführen. Wird
die PowerShell bei der Ausführung gehindert, startet sie im eingeschränkten Sprach-modus. Dazu müssen Sie
lediglich das Ausführen von Skripten im Ordner $env:TEMP verbieten.
Realisieren können Sie das z.B. per Softwareeinschränkung (GPO) unter Computerkonfiguration /
Windows-Einstellungen / Sicherheitseinstellungen / Richtlinien für Softwareeinschränkung
/ Zusätzliche Regeln.
# TODO Test-Umgebung: Neu Pfad-Regel erstellen für
C:UsersAttilaAppDataLocalTemp :
GPEdit.msc
Oder per AppLocker unter Computerkonfiguration / Windows-Einstellungen /
Sicherheitseinstellungen / Anwendungssteuerungsrichtlinien / AppLocker / Skriptregeln.
Umgang mit Zugriffsberechtigungen (ACL)
Die PowerShell-Board-Mittel sind leider noch überschaubar. Im Grunde können wir von einem vorhandenes
Windows-Objekt, dessen Access-Control-List klonen und genau diese auf ein anderes Objekt übertragen.
Windows Terminal Screenshot - ACL auswerten und Berechtigungen im Klartext anzeigen
# ! Die PowerShell-Board-Mittel:
Get-Command -Name 'Get-Acl', 'Set-Acl', 'ConvertFrom-SddlString'
# ? Berechtigungen von Ordner-A auf Ordner-B übertragen:
New-Item -Path 'C:' -Name 'TempTest' -ItemType 'Directory' -Force
Get-Acl -Path 'C:Temp' | Select-Object -Property '*'
Get-Acl -Path 'C:Temp' | Set-Acl -Path 'C:TempTest'
# TODO Aufräumen:
Remove-Item -Path 'C:TempTest' -Recurse -Force
12. C12_Sicherheit-an-PowerShell.md 7/11/2020
12 / 18
ACL-Objekte sind mit unter oft kryptisch zu lesen (gacutil.exe) aber lesen und auswerten bekommen wir über
das Cmdlet ConvertFrom-SddlString Unterstützung.
# ? Berechtigungen von ACL-Objekten auswerten:
Get-Acl -Path $env:USERPROFILE | Select-Object -ExpandProperty 'Sddl' |
ConvertFrom-SddlString
Umfassende/aufwendige Möglichkeiten ergeben sich mit .NET oder Sie schauen Sich das Modul
NtfsSecurity aus der PowerShall-Gallery einmal genauer an.
Install-Module -Name 'NTFSSecurity' -Scope 'CurrentUser' -SkipPublisherCheck -
Force -PassThru -Verbose
Get-Command -Module 'NTFSSecurity'
Get-NTFSAccess -Path 'C:Temp'
# TODO Aufräumen:
Remove-Module -Name 'NTFSSecurity' -Force
Uninstall-Module -Name 'NTFSSecurity' -AllVersions -Force
Admin-Aufgaben an Nicht-Admins delegieren (JEA)
Neben den bereits beschriebenen PowerShell Sicherheit-Mechaniken ist die Königsdisziplin, um die
PowerShell Sicherheit auf ein Maximum zu heben das Feature "Just Enough Administration". Dieses vereint die
bereits aufgeführten Funktionen und ergänzt diese.
Just Enough Administration (JEA => Gerade genug Administration) ist ein Feature, das ab Windows 10 und
Server 2016 zur Verfügung steht. Mit JEA (Just Enough Administration) können Systemverwalter mittels
PowerShell granular administrative Aufgaben an Nicht-Administratoren delegieren.
Diese Nicht-Administrator erhalten, unabhängig von der Gruppenmitgliedschaft über eine Remote-Session
mittels "Just Enough Administration"-Zugriff auf vorher festgelegte Komponenten (PSProvider, Cmdlets,
Cmdlet-Parameter, Ausführbare Dateien, etc.).
Das damit realisierte Prinzip "Least Privilege" sieht vor, nur noch die tatsächlich minimalen Rechte für
bestimmte Aufgaben und Dienste an administrative Mitarbeiter zu erteilen.
Die Architektur basiert auf "Just Enough Administration"-Endpoints, mit denen sich der Bediener via Enter-
PSSession verbindet und remote Befehle mit höheren Rechten auf Systemen ausführen kann.
Umfassende Details finden Sie in der Microsoft Dokumentation Just Enough Administration.
HINWEIS - Sollten Sie dieses Beispiel unter PowerShell 7 auf Windows-Rechnern ausführen sind
folgende Schritte nötig.
Import-WinModule -Name 'NetAdapter'
Import-WinModule -Name 'NetConnection'
Import-WinModule -Name 'Microsoft.PowerShell.LocalAccounts'
13. C12_Sicherheit-an-PowerShell.md 7/11/2020
13 / 18
1. JEA Voraussetzungen prüfen
Just Enough Administration ist ein in Feature ab PowerShell 5.0. Dazu gesellen sich noch weitere
Voraussetzungen, die wir zuerst einmal abklopfen sollten.
# ? PowerShell-Version:
$PSVersionTable.PSVersion -ge [Version]"5.0.0.0"
# ? OS-Version:
Get-ComputerInfo | ForEach-Object { if(($_.OsName -IMatch 'Windows 10' -and
$_.WindowsVersion -ge 1607) -or $_.OsName -IMatch 'Windows Server 2016' -or
$_.OsName -imatch 'Windows Server 2019') { $true } else { $false } }
# ? PS Remoting aktiviert:
try { Invoke-Command -ComputerName 'localhost' -ScriptBlock { 1 | Out-Null } -
Credential (Get-Credential) -ErrorAction Stop ; $true } catch { $false }
In diesem Artikel Just Enough Administration Voraussetzungen werden die Voraussetzungen erläutert, die
erfüllt sein müssen, um "Just Enough Administration" verwenden zu können.
2. Vorbereitungen für "Just Enough Administration" treffen
Im folgenden Code-Block treffen wir die Vorbereitungen für das Testszenario. Dieses Szenario kann komplett
lokal ausgeführt werden ohne dass eine Domänenmitgliedschaft nötig ist.
# TODO Remoting auf Bediener-PC und Wartungs-Server aktivieren:
Get-NetAdapter -Physical | Set-NetConnectionProfile -NetworkCategory 'Private' -
PassThru
Enable-PSRemoting -Force
Set-Item -Path 'WSMan:localhostClientTrustedHosts' -Value '*' -Force
# !TODO Auf dem Wartungs-Server bzw. AD-Domäne Nicht-Admin-Benutzer und -Gruppe
festlegen / erstellen die Verwaltungsaufgaben erledigen müssen:
$NewUser = @{
Name = 'DruckerHorst'
AccountExpires = (Get-Date).AddHours(24)
Description = "24h Demo-Drucker-Managers ohne Admin-Rechte."
Password = (Read-Host -Prompt "Passwort für DruckerHorst" -
AsSecureString)
PasswordNeverExpires = $true
UserMayNotChangePassword = $true
}
New-LocalUser @NewUser
New-LocalGroup -Name 'LocalPrinterManagerGroup' -Description 'JEA-Demo:
DruckerManager-Gruppe für nicht Admins'
Add-LocalGroupMember -Group 'LocalPrinterManagerGroup' -Member 'DruckerHorst'
14. C12_Sicherheit-an-PowerShell.md 7/11/2020
14 / 18
3. Module-Ordner erstellen
Den JEA-PowerShell-Module-Ordner auf dem Wartungsserver erstellen in dem später die
Rollenfunktionsdateien (Role Capabilities) gesucht werden.
WICHTIG - Der folgende Modul-Ordner muss vor Manipulation geschützt werden, Stichwort ACL.
# Für PowerShell 7:
$ModulePath = "$env:ProgramFilesPowerShellModulesAbcFirma"
# Für Windows PowerShell:
$ModulePath = "$env:ProgramFilesWindowsPowerShellModulesAbcFirma"
New-Item -Path $ModulePath -ItemType 'Directory'
New-ModuleManifest -Path "$ModulePathAbcFirma.psd1" -RootModule 'AbcFirma'
4. Rollenfunktions-Datei erstellen
In dieser/n Rollenfunktionsdatei(en) (PowerShell Role Capability File .PSRC) legen Sie fest welche Rolle was auf
dem Wartungs-Server machen darf.
New-Item -Path "$ModulePathRoleCapabilities" -ItemType 'Directory'
$Parameter = @{
Path =
"$ModulePathRoleCapabilitiesPrinterManagerRoleCapability.psrc"
Author = 'Attila Krick'
CompanyName = 'ATTILAKRICK.COM'
Description = 'Benötigte Tools für Drucker-Manager.'
ModulesToImport = 'Microsoft.PowerShell.Management',
'Microsoft.PowerShell.Core', 'Microsoft.PowerShell.Utility'
VisibleProviders = 'FileSystem', 'Environment', 'Registry'
VisibleCmdlets = 'Clear-Host', 'Exit-PSSession', 'Get-Command', 'Get-
ChildItem', 'Get-FormatData', 'Get-Help', 'Measure-Object', 'Out-Default', 'Out-
String', 'Select-Object', `
@{ Name = 'Restart-Computer'; Parameters = @{ Name =
'ComputerName' ; ValidatePattern = 'VDId+' } }, `
@{ Name = 'Restart-Service' ; Parameters = @{ Name =
'Name' ; ValidateSet = 'Dns', 'Spooler' } }
FunctionDefinitions = @{ Name = 'Get-UserInfo' ; ScriptBlock = {
$PSSenderInfo } }
VisibleExternalCommands = 'C:WindowsSystem32WhoAmI.exe'
}
New-PSRoleCapabilityFile @Parameter
# TODO Kontrolle:
Start-Process -FilePath
"$ModulePathRoleCapabilitiesPrinterManagerRoleCapability.psrc"
15. C12_Sicherheit-an-PowerShell.md 7/11/2020
15 / 18
Weitere Details finden Sie in der Microsoft Dokumentation Erstellen einer Rollenfunktionsdatei.
5. Sitzungskonfigurations-Datei erstellen
In dieser Sitzungskonfigurations-Datei (PowerShell Session Configuration File .PSSC) wird die Nicht-Admin-
Gruppe(n) mit der entsprechenden Rolle verknüpft.
New-Item -Path "$env:ProgramDataJEASessionConfigurations" -ItemType 'Directory'
$JEAConfigParams = @{
Path =
"$env:ProgramDataJEASessionConfigurationsJEAPrintServerSession.pssc"
Author = 'Attila Krick'
Description = 'Verbindet die Rollen (u.a. Drucker-Manager) mit dieser
Session (JEAPrintServerSession)'
CompanyName = 'ATTILAKRICK.COM'
SessionType = "Default" # ! PROBLEM: "RestrictedRemoteServer"
RunAsVirtualAccount = $true
TranscriptDirectory = "$env:ProgramDataJEASessionConfigurationsTranscripts"
RoleDefinitions = @{ 'LocalPrinterManagerGroup' = @{RoleCapabilities =
'PrinterManagerRoleCapability'}}
Full = $true
}
New-PSSessionConfigurationFile @JEAConfigParams
# ! Kontrolle:
Test-PSSessionConfigurationFile -Path
"$env:ProgramDataJEASessionConfigurationsJEAPrintServerSession.pssc"
Start-Process -FilePath
"$env:ProgramDataJEASessionConfigurationsJEAPrintServerSession.pssc"
Weitere Details finden Sie in der Microsoft Dokumentation JEA-Sitzungskonfigurationen sowie unter Get-
Help -Name 'about_Session_Configuration_Files' -ShowWindow.
6. Die Sitzungskonfiguration registrieren und etablieren
Jetzt können wir Sitzungskonfiguration registrieren und den Endpoint etablieren, um so JEA für den Bediener
zu aktivieren.
Register-PSSessionConfiguration -Name 'JEAPrintServerSession' -Path
"$env:ProgramDataJEASessionConfigurationsJEAPrintServerSession.pssc" -Force
Restart-Service WinRM
# ! Kontrolle - Übersicht der registrierten Sitzungskonfigurationen:
Get-PSSessionConfiguration | Select-Object Name, Permission
Weitere Details finden Sie in der Microsoft Dokumentation Registrieren von JEA-Konfigurationen.
7. Just Enough Administration als Bediener/Verwalter verwenden
16. C12_Sicherheit-an-PowerShell.md 7/11/2020
16 / 18
Jetzt zeigt es sich, wie es um die PowerShell Sicherheit gestellt ist.
# TODO 1. Per Just Enough Administration (JEA) sich mit dem zu verwalten Server
als Nicht-Admin per Remote verbinden:
$cred = Get-Credential -UserName 'DruckerHorst' -Message 'Credential für
localhost'
# ! Administrator-Remote-Verbindung ist NICHT erlaubt:
Enter-PSSession -ComputerName 'localhost' -Credential $cred
# * JEA-Remote-Verbindung ist ERLAUBT:
Enter-PSSession -ComputerName 'localhost' -ConfigurationName
'JEAPrintServerSession' -Credential $cred
# ! 2. Eine Übersicht der Rechte für Benutzer X:
Get-PSSessionCapability -ConfigurationName "JEAPrintServerSession" -Username
"DruckerHorst" -Full
# ! 3. Just Enough Administration testen:
C:WindowsSystem32WhoAmI.exe # * erlaubt
Get-ChildItem -Path Hkcu: # * erlaubt
Restart-Service -Name Spooler # * erlaubt
Restart-Service -Name AudioSrv # ! Nicht erlaubt
Restart-Computer -ComputerName localhost # ! Nicht erlaubt
Restart-Computer -ComputerName VDI009 # * erlaubt
Get-UserInfo # * erlaubt
Get-Command # * erlaubt
exit # * erlaubt
Weitere Details finden Sie in der Microsoft Dokumentation [Verwenden von JEA]
(https://docs.microsoft.com/de-de/powershell/scripting/learn/remoting/jea/register-jea).
8. Aufgezeigt Konfiguration zurücksetzen
Aufgezeigt Konfiguration wieder rückgängig machen und sämtliche Spuren beseitigen
Unregister-PSSessionConfiguration -Name 'JEAPrintServerSession'
Restart-Service -Name 'WinRM'
Remove-Item -Path
"$env:ProgramDataJEASessionConfigurationsJEAPrintServerSession.pssc" -Force
Remove-Item -Path "$env:ProgramFilesPowerShellModulesAbcFirma" -Recurse -Force
Remove-Item -Path "$env:ProgramFilesWindowsPowerShellModulesAbcFirma" -Recurse
-Force
Remove-LocalGroup -Name 'LocalPrinterManagerGroup'
Remove-LocalUser -Name 'DruckerHorst'
Set-Item -Path "WSMan:localhostClientTrustedHosts" -Value ([String]::Empty) -
Force
Disable-PSRemoting -Force
Get-NetAdapter -Physical | Set-NetConnectionProfile -NetworkCategory "Public"
17. C12_Sicherheit-an-PowerShell.md 7/11/2020
17 / 18
PowerShell Sicherheit per GPO verteilen
PowerShell Sicherheit per GPO in der ActiveDirectory-Domäne verteilen.
EdgeUI.admx
User / Windows Components / Edge UI / Prevent users from replacing the Command Prompt
with Windows PowerShell in the menu they see when they right-click the lower-left
corner or press the Windows logo key+X
HKCUSoftwarePoliciesMicrosoftWindowsEdgeUI!ShowCommandPromptOnWinX
PowerShellExecutionPolicy.admx
Machine / Windows Components / Windows PowerShell / Turn on PowerShell Script Block
Logging
HKLMSoftwarePoliciesMicrosoftWindowsPowerShellScriptBlockLogging!EnableScriptBlockLo
gging
HKLMSoftwarePoliciesMicrosoftWindowsPowerShellScriptBlockLogging!EnableScriptBlockIn
vocationLogging
User / Windows Components / Windows PowerShell / Turn on PowerShell Script Block
Logging
HKCUSoftwarePoliciesMicrosoftWindowsPowerShellScriptBlockLogging!EnableScriptBlockLo
gging
HKCUSoftwarePoliciesMicrosoftWindowsPowerShellScriptBlockLogging!EnableScriptBlockIn
vocationLogging
Machine / Windows Components / Windows PowerShell / Turn on PowerShell Transcription
HKLMSoftwarePoliciesMicrosoftWindowsPowerShellTranscription!EnableTranscripting
HKLMSoftwarePoliciesMicrosoftWindowsPowerShellTranscription!OutputDirectory
HKLMSoftwarePoliciesMicrosoftWindowsPowerShellTranscription!EnableInvocationHeader
User / Windows Components / Windows PowerShell / Turn on PowerShell Transcription
HKCUSoftwarePoliciesMicrosoftWindowsPowerShellTranscription!EnableTranscripting
HKCUSoftwarePoliciesMicrosoftWindowsPowerShellTranscription!OutputDirectory
HKCUSoftwarePoliciesMicrosoftWindowsPowerShellTranscription!EnableInvocationHeader
Epilog
Von mir gibt es noch weitere PowerShell-Fachartikel und Guides. Und jetzt Neu, abonnieren Sie meinen
PowerShell-YouTube-Kanal.
Oder Wissen vom Trainer mit vielen praxisbezogenen Übungen, Wissenstests und Frage und Antwort-Runden.
Jetzt in meinen PowerShell-Seminaren und -Workshops.
Wenn Sie diesen Artikel als hilfreich empfunden haben würde ich mich über eine Erwähnung und einen
Verweis auf diesen Artikel in den sozialen Medien sehr freuen.
Als Dankeschön bekommen Sie ein von mir erstelltes hochwertiges A1-PowerShell-7-Poster mit den
wichtigsten Informationen für die tägliche Arbeit per Post zugesendet. Hierzu schreiben Sie mir an info at
attilakrick.com einfache eine E-Mail mit dem Link der Erwähnung sowie Ihre Adresse. Aber nur solange der
18. C12_Sicherheit-an-PowerShell.md 7/11/2020
18 / 18
Vorrat reicht. Ihre Daten (E-Mail, Adresse) werden nur zum Zweck des Poster-Versandes benötigt und
anschließend gelöscht.
[site_reviews_form title="Bitte bewerten Sie diesen Artikel" category="121" assign_to="258" id="kcb17qh9"
hide="title,content,name,email,terms"]