Private/Wissen/C_Scripting/C11_Sicherheit.ps1
# ? TITEL Sicherheit # ? DESCRIPTION PowerShell absichern und mit Sicherheit in der PowerShell umgehen # ? TAGS Sicherheit Security PKI NTFS Security Crypt Decrypt Signature Credentials ActiveDirectory GPO ScriptBlockLogging Transcript CLM PSRC PSSC # ? VERSION 2020.01.28 # TODO Weiterführende und Nachschlage-Informationen # TODO siehe C02_Ausführungsrichtlinien.ps1, C08_ScripteSignieren.ps1, X11_Technology_Hacking.ps1 # TODO Vergleich Sicherheitsmechanismen div. Script-Sprachen https://devblogs.microsoft.com/powershell/a-comparison-of-shell-and-scripting-language-security/ # TODO betroffene about-Seiten: Get-Help -Name about_Execution_Policy -ShowWindow <# ! Die PowerShell ist im System verwurzelt. Daher sorgt ein generelles Blockieren nur für scheinbare Sicherheit. ! Den besten Schutz versprechen letztlich die Schutzmechanismen von PowerShell selbst. ! Neben Mitteln, die den Missbrauch von PowerShell unterbinden, stehen auch solche zur Verfügung, ! um verdächtigen und unerwünschten Aktivitäten zu protokollieren und diese auf die Spur zu kommen. #> # !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! # !!! Unbedingt sollten Sie PowerShell 2.0 entfernen. Mit dieser alten Shell 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. !!! # !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! #region Zufallszahlen & -text erzeugen # ? Zufallstext z.B. für Initialpasswort: [System.IO.Path]::GetRandomFileName() -replace "\.", [String]::Empty # ? Zufallszahlen: 1..100 | Get-Random -Count 3 (1..100 | Get-Random -Count 3 | ForEach-Object {"{0:00}" -f $_}) -join [String]::Empty [Convert]::ToBase64String((0..255 | Get-Random -Count 9)) #endregion #region SecureString # ? betroffene Cmdlets: Get-command -Noun SecureString -Module Microsoft.PowerShell.Security # ? Ein Passwort verschlüsselt aufbewarben und sicher einlesen verwenden: Read-Host -Prompt "Passwort eingeben" -AsSecureString | ConvertFrom-SecureString | Out-File -FilePath "C:\temp\SecureString.txt" -Force Get-Content -Path "C:\Temp\SecureString.txt" | ConvertTo-SecureString #endregion #region Credentials # ? Credential sicher im RAM aufbewahren: $cred = Get-Credential -Message "Zugangsdaten für Administrator auf ExServer4711" -UserName "Administrator" # ? Credential verschlüsselt speichern: $username = Read-Host -Prompt "Benutzername eingaben" $password = Read-Host -Prompt "Passwort für $username eingeben" -AsSecureString [PSCustomObject]@{ Username = $username Password = $password | ConvertFrom-SecureString } | ConvertTo-Json | Set-Content -Path C:\Temp\Credential_Admin.json -Force $admin = Get-Content -Path C:\Temp\Credential_Admin.json | ConvertFrom-Json | Select-Object Username, @{Label="Password"; Expression={$_.Password | ConvertTo-SecureString}} $cred = [System.Management.Automation.PSCredential]::new($admin.Username, $admin.Password) Enter-PSSession -ComputerName "127.0.0.1" -Credential $cred #endregion #region PKI # TODO Siehe C08_ScripteSignieren.ps1 # ? betroffene Cmdlets: Get-Command -Name * -Module PKI #endregion #region Zeichenketten verschlüsseln # ? betroffene Cmdlets: Get-Command -Noun "CmsMessage" -Module "Microsoft.PowerShell.Security" # ! Siehe auch: CipherNet Lite => Funktionsbibliothek zum Thema Verschlüsselung $params = @{ Subject = "CN=_Doctor Crypt (Test-Verschlüssler), E=d.crypt@test.local" HashAlgorithm = "SHA512" KeyExportPolicy = [Microsoft.CertificateServices.Commands.KeyExportPolicy]::ExportableEncrypted KeyLength = 4096 KeySpec = [Microsoft.CertificateServices.Commands.KeySpec]::KeyExchange CertStoreLocation = "Cert:\CurrentUser\My" Type = [Microsoft.CertificateServices.Commands.CertificateType]::DocumentEncryptionCert NotAfter = (Get-Date).AddMinutes(60) } $myPfxCert = New-SelfSignedCertificate @params $cryptedText = "Hallo Würzburg!" | Protect-CmsMessage -To $myPfxCert.Thumbprint $cryptedText $cryptedText | Unprotect-CmsMessage -To $myPfxCert.Thumbprint Get-ChildItem -Path Cert:\CurrentUser\My | Where-Object -Property Thumbprint -eq -Value $myPfxCert.Thumbprint | Remove-Item #endregion #region Umgang mit Zugriffsberechtigungen # ! Die PowerShell-Board-Mittel sind leider sehr überschaubar. ... # ? betroffene Cmdlets: Get-Command "*acl*" -Module "Microsoft.PowerShell.Security" # ? Berechtigungen von Ordner-A auf Ordner-B übetragen: 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" # ! ... Umfassende /aufwendige Möglichkeiten ergeben sich mit dem .NET. ... # ! ... oder Sie schauen Sich das Module NTFSSecurity aus der PowerShallGallery einmal an: Install-Module -Name "NTFSSecurity" -SkipPublisherCheck -Scope "CurrentUser" -Force -PassThru -Verbose Get-command -Module "NTFSSecurity" Get-NTFSAccess -Path "C:\Temp" #endregion #region Scripte Signieren # TODO siehe C08_ScripteSignieren.ps1, X21_Technology_PKI.ps1 $MyCert = Get-PfxCertificate -FilePath ".\AKPT\Private\Wissen\X_Technology\X98_Kryptonite.pfx" $MyCert | Export-Certificate -FilePath "C:\Temp\Kryptonite.cer" Import-Certificate -FilePath "C:\Temp\Kryptonite.cer" -CertStoreLocation "Cert:\LocalMachine\Root" "' > > > Hallo Welt! < < < ' | Write-Host -ForegroundColor Red -BackgroundColor Yellow" | Set-Content -Path "c:\Temp\Get-HalloWelt.ps1" -Force # ! Datei signieren: $params = @{ Certificate = $MyCert FilePath = "C:\Temp\Get-HalloWelt.ps1" TimestampServer = "http://timestamp.globalsign.com/scripts/timstamp.dll" IncludeChain = "all" HashAlgorithm = "SHA512" Force = $true } Set-AuthenticodeSignature @params # ! Signierte Datei validieren: "C:\Temp\Get-HalloWelt.ps1" | Get-AuthenticodeSignature | Select-Object -Property * #endregion #region Ausführungsrichtlinien # TODO siehe C02_Ausführungsrichtlinien.ps1 # TODO betroffene about-Seiten: Get-Help -Name "about_Execution_Policy" -ShowWindow # ? Wie ist die ExecutionPolicy eingestellt: Get-ExecutionPolicy -List # ? Wie ist die ExecutionPolicy für den aktuellen Script-Host eingestellt: $env:PSExecutionPolicyPreference # ! Set-ExecutionPolicy steuert folgende Registry-Properties: Get-ItemPropertyValue -Path "Registry::HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\PowerShell\1\ShellIds\Microsoft.PowerShell" -Name "ExecutionPolicy" Get-ItemPropertyValue -Path "Registry::HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\PowerShell\1\ShellIds\ScriptedDiagnostics" -Name "ExecutionPolicy" Get-ItemPropertyValue -Path "Registry::HKEY_CURRENT_USER\Software\Microsoft\PowerShell\1\ShellIds\Microsoft.PowerShell" -Name "ExecutionPolicy" # ? Empfohlene Einstellung für Client und Server Set-ExecutionPolicy -ExecutionPolicy AllSigned # TODO siehe: Get-Help -Name about_Signing -ShowWindow # ! d.h. alle ausführbare Dateien müssen signiert (x.509-Zertifikat) sein # ? Empfohlene Einstellung für Test-/Entwicklungszwecke (Remote-Scripte müssen signiert sein) Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope LocalMachine -Force # ! Bzgl. RemoteSign werden Dateien an einem Download-Marker identifiziert! siehe Cmdlet: Unblock-File #endregion #region PowerShell in der ActiveDirectory-Domäne per GPO absichern <# ! EdgeUI.admx ? 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 User - Windows Components\Edge UI HKCU\Software\Policies\Microsoft\Windows\EdgeUI!ShowCommandPromptOnWinX ! PowerShellExecutionPolicy.admx ? Turn on PowerShell Script Block Logging Machine - Windows Components\Windows PowerShell HKLM\Software\Policies\Microsoft\Windows\PowerShell\ScriptBlockLogging!EnableScriptBlockLogging HKLM\Software\Policies\Microsoft\Windows\PowerShell\ScriptBlockLogging!EnableScriptBlockInvocationLogging ? Turn on PowerShell Script Block Logging User - Windows Components\Windows PowerShell HKCU\Software\Policies\Microsoft\Windows\PowerShell\ScriptBlockLogging!EnableScriptBlockLogging HKCU\Software\Policies\Microsoft\Windows\PowerShell\ScriptBlockLogging!EnableScriptBlockInvocationLogging ? Turn on PowerShell Transcription Machine - Windows Components\Windows PowerShell HKLM\Software\Policies\Microsoft\Windows\PowerShell\Transcription!EnableTranscripting HKLM\Software\Policies\Microsoft\Windows\PowerShell\Transcription!OutputDirectory HKLM\Software\Policies\Microsoft\Windows\PowerShell\Transcription!EnableInvocationHeader ? Turn on PowerShell Transcription User - Windows Components\Windows PowerShell HKCU\Software\Policies\Microsoft\Windows\PowerShell\Transcription!EnableTranscripting HKCU\Software\Policies\Microsoft\Windows\PowerShell\Transcription!OutputDirectory HKCU\Software\Policies\Microsoft\Windows\PowerShell\Transcription!EnableInvocationHeader ! Scripts.admx ? Run Windows PowerShell scripts first at computer startup, shutdown Machine - System\Scripts HKLM\Software\Microsoft\Windows\CurrentVersion\Policies\System!RunComputerPSScriptsFirst ? Run Windows PowerShell scripts first at user logon, logoff Machine - System\Scripts HKLM\Software\Microsoft\Windows\CurrentVersion\Policies\System!RunUserPSScriptsFirst ? Run Windows PowerShell scripts first at user logon, logoff User - System\Scripts HKCU\Software\Microsoft\Windows\CurrentVersion\Policies\System!RunUserPSScriptsFirst #> #endregion #region ScriptBlockLogging (Protokollierung von PowerShell-Scriptblöcken) # ? Variante A: Host-Ein-/Ausgabe protokollieren per Start-Transcript: Start-Transcript -Path "C:\Temp\PsHost.log" -Append -Force # ! Transcript starten Get-Process # ! Test Eingabe & Ausgaben Read-Host -Prompt "Passwort eingeben" -AsSecureString # ! Test Eingabe & Ausgaben Stop-Transcript -Verbose # ! Transcript stoppen Start-Process -FilePath "C:\Temp\PsHost.log" # ! Log-Datei anzeigen # ? Variante B: Permanentes und sicheres Protokollieren sämtlicher Host's aktivieren (auch per GPO) # ? Per GPO: Computerkonfiguration / Administrative Vorlagen / Windows-Komponenten / # ? Windows PowerShell / Protokollierung von PowerShell-Scriptblöcken aktivieren # ! Betrifft PowerShell 7: # ! Im Gegensatz zu Linux oder macOS muss in Windows der Ereignisanbieter registriert sein, # ! bevor Ereignisse in das Ereignisprotokoll geschrieben werden können. # ! Führen Sie mit erhöhten Berechtigungen folgendes Script aus: # ! siehe auch: Get-Help -Name about_logging_windows -ShowWindow . "$PsHome\RegisterManifest.ps1" # * -Unregister Get-WinEvent -ListProvider *powershell* | Select-Object -Property Name # ! ... für Windows PowerShell und PowerShell 7 (64/32bit): New-Item -Path "Registry::HKEY_LOCAL_MACHINE\SOFTWARE\Policies\Microsoft\Windows\PowerShell" -Name "ScriptBlockLogging" -ItemType "Key" -Force | New-ItemProperty -Name "EnableScriptBlockLogging" -Value "1" -PropertyType "DWord" -Force # TODO Registry::HKEY_LOCAL_MACHINE\SOFTWARE\Policies\Microsoft\Windows\PowerShellCore\ScriptBlockLogging # TODO Registry::HKEY_LOCAL_MACHINE\SOFTWARE\WOW6432Node\Policies\Microsoft\Windows\PowerShell\ScriptBlockLogging # TODO Registry::HKEY_LOCAL_MACHINE\SOFTWARE\WOW6432Node\Policies\Microsoft\Windows\PowerShellCore\ScriptBlockLogging # ? Windows-Log auswerten (ID 4104 in Microsoft-Windows-PowerShell/Operational bzw. PowerShellCore/Operational) # ! ... für Windows PowerShell bzw. PowerShellCore/Operational: Get-WinEvent -FilterHashtable @{LogName="Microsoft-Windows-PowerShell/Operational" ; Id="4104" } | Select-Object -Property "RecordId", "ProcessId", "MachineName", "UserId", "TimeCreated", "Message" | Sort-Object -Property "TimeCreated" | Select-Object -Last 5 # TODO da noch Fehlerhaft: Get-WinEvent -LogName "Windows PowerShell" -MaxEvents 5 | Where-Object Id -eq 4104 | Select-Object -exp Message # !!! Um sensible Daten zu schützen sollten diese Log's verschlüsselt werden (s. Protected Event Logging) !!! Get-Help -Name about_logging_windows -ShowWindow # ! ScriptBlockLogging deaktivieren Set-ItemProperty -Path "Registry::HKEY_LOCAL_MACHINE\SOFTWARE\Policies\Microsoft\Windows\PowerShell\ScriptBlockLogging" -Name "EnableScriptBlockLogging" -Value 0 Set-ItemProperty -Path "Registry::HKEY_LOCAL_MACHINE\SOFTWARE\Policies\Microsoft\Windows\PowerShellCore\ScriptBlockLogging" -Name "EnableScriptBlockLogging" -Value 0 Set-ItemProperty -Path "Registry::HKEY_LOCAL_MACHINE\SOFTWARE\WOW6432Node\Policies\Microsoft\Windows\PowerShell\ScriptBlockLogging" -Name "EnableScriptBlockLogging" -Value 0 Set-ItemProperty -Path "Registry::HKEY_LOCAL_MACHINE\SOFTWARE\WOW6432Node\Policies\Microsoft\Windows\PowerShellCore\ScriptBlockLogging" -Name "EnableScriptBlockLogging" -Value 0 #endregion #region Eine PowerShell-Session einschränken (RestrictedLanguage incl. Allowed Cmdlets) $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" # ! Keine Anwendungen und Skripte ab jetzt erlauben: $ExecutionContext.SessionState.Applications.Clear() $ExecutionContext.SessionState.Scripts.Clear() # ! Nicht erlaubte Cmdlets unsichtbar machen: Get-Command -CommandType "Cmdlet", "Function" | Where-Object -FilterScript { $allowedCommands -NotContains $_.Name } | ForEach-Object -Process { $_.Visibility = "Private" } $ExecutionContext.SessionState.LanguageMode = "RestrictedLanguage" #endregion #region Aktivieren des eingeschränkten PowerShell-Sprachmodi (Constrained Language Mode (CLM)) # ! Zu den wichtigsten Sicherheitsmechanismen gehört der 'Constrained Language Mode', # ! der mehrere gefährliche PowerShell-Features deaktiviert und verhindert so deren Missbrauch. Get-Help -Name About_Language_Modes -ShowWindow Get-Help -Name about_ConstrainedLanguage -ShowWindow Get-Help -Name about_FullLanguage -ShowWindow Get-Help -Name about_NoLanguage -ShowWindow Get-Help -Name about_RestrictedLanguage -ShowWindow Get-Help -Name about_Session_Configurations -ShowWindow Get-Help -Name about_Session_ConfigurationFiles -ShowWindow # ? Den 'Constrained Language Mode' aktivieren: $ExecutionContext.SessionState.LanguageMode = [System.Management.Automation.PSLanguageMode]::ConstrainedLanguage # *? Default => FullLanguage # ! ACHTUNG: Ein anschließendes Zurückstellen in der aktuellen Sitzung ist nicht mehr möglich! # ? Den 'Constrained Language Mode' DAUERHAFT aktivieren: [Environment]::SetEnvironmentVariable("__PSLockDownPolicy", "4", "Machine") # 1 => FullLanguage $env:__PSLockDownPolicy # ! Die Folge ist, das jeder PowerShell-Host (Console, ISE, VSCode, etc.) im eingeschränkten Modus startet! # ? Eine automatische Erkennung einer Ausführungsbeschränkung (Constrained Language Mode) aktivieren: # * Seit PowerShell 5 wird automatisch erkannt ob in den 'Constrained Language Mode' gewechselt 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 Sprachmodus. # * Dazu müssen Sie lediglich das Ausführen von Skripten im Ordner: $env:TEMP # * verbieten. Realisieren können Sie das per Softwareeinschränkung (GPO) unter: # ! Computerkonfiguration / Windows-Einstellungen / Sicherheitseinstellungen / Richtlinien für Softwareeinschränkung / Zusätzliche Regeln # * oder per AppLocker unter: # ! Computerkonfiguration / Windows-Einstellungen / Sicherheitseinstellungen / Anwendungssteuerungsrichtlinien / AppLocker / Skriptregeln #endregion #region PowerShell-Remoting absichern # ! siehe unter: Just Enough Administration (JEA) #endregion #region Admin-Aufgaben delegieren mit Just Enough Administration (JEA) # TODO siehe Just Enough Administration (https://docs.microsoft.com/de-de/powershell/scripting/learn/remoting/jea/overview?view=powershell-7) <# ! Kurzbeschreibung Just enough Administration (JEA => Gerade genug Administration) ist ein Feature in Windows 10 und Server 2016, mit der sich die Systemverwaltung mittels PowerShell granular delegieren lässt. Nicht-Administrator erhalten unabhängig von der Gruppenmitgliedschaft über eine Remote-Session mittels JEA zugriff auf bestimmte Cmdlets oder gar einzelne ihrer Parameter. 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 immer auf JEA-Endpoints, mit denen sich der Bediener via Enter-PSSession verbindet und remote Befehle mit höheren Rechten auf Systemen ausführen kann. #> #region 1. Voraussetzungen prüfen # TODO siehe https://docs.microsoft.com/de-de/powershell/scripting/learn/remoting/jea/prerequisites?view=powershell-7 # ? 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") { $true } else { $false } } # ? PS Remoting aktiv: try { Invoke-Command -ComputerName "localhost" -ScriptBlock { 1 } -ErrorAction Stop ; $true } catch { $false } #endregion #region 2. Vorbereitungen treffen # ! Remoting auf Bediener-PC und Wartungs-Server aktivieren (beachte auch B09_Remoting.ps1): Get-NetAdapter -Physical | Set-NetConnectionProfile -NetworkCategory "Private" -PassThru Enable-PSRemoting -SkipNetworkProfileCheck -Force Set-Item -Path "WSMan:\localhost\Client\TrustedHosts" -Value "*" -Force # ! Auf dem Wartungs-Server Nicht-Admin-Benutzer und -Gruppe festlegen / erstellen die Verwaltungsaufgaben erledigen sollen: $NoAdminUser = "TestHorst" $MaintenanceGroup = "_Demo_NichtAdmins" $NewUser = @{ Name = $NoAdminUser AccountExpires = (Get-Date).AddHours(24) Description = "24h Demo-Account" Password = (Read-Host -Prompt "Passwort für $NoAdminUser" -AsSecureString) PasswordNeverExpires = $true UserMayNotChangePassword = $true } New-LocalUser @NewUser New-LocalGroup -Name $MaintenanceGroup -Description "JEA-Demo: Gruppe für nicht Admins" Add-LocalGroupMember -Group $MaintenanceGroup -Member $NoAdminUser #endregion #region 3. JEA Module erstellen in dem später Role Capabilities gesucht werden $ModuleName = "_FirmaAG_JEA" $ModulePath = Join-Path -Path $env:ProgramFiles -ChildPath "WindowsPowerShell\Modules\$ModuleName" New-Item -ItemType Directory -Path $ModulePath New-Item -ItemType File -Path (Join-Path -Path $ModulePath -ChildPath "$ModuleName.psm1") New-ModuleManifest -Path (Join-Path -Path $ModulePath -ChildPath "$ModuleName.psd1") -RootModule "$ModuleName" #endregion #region 4. Eine Rollenfunktionsdatei (PowerShell Role Capability File (.PSRC)) erstellen # TODO siehe JEA-Rollenfunktionen (https://docs.microsoft.com/de-de/powershell/scripting/learn/remoting/jea/role-capabilities?view=powershell-7#create-a-role-capability-file) $RoleCapabilitiesPath = Join-Path -Path $ModulePath -ChildPath "RoleCapabilities" New-Item -ItemType Directory -Path $RoleCapabilitiesPath $MaintenanceRoleCapPath = Join-Path -Path $RoleCapabilitiesPath -ChildPath "Maintenance.psrc" $MaintenanceRoleCapabilityCreationParams = @{ Path = $MaintenanceRoleCapPath Author = "Attila Krick" CompanyName = "attilakrick.com" ModulesToImport = "Microsoft.PowerShell.Core" VisibleProviders = "Registry" VisibleCmdlets = "Out-Default", ` "Get-Command", ` "Get-ChildItem", ` "Out-String", ` @{ Name = "Restart-Computer"; Parameters = @{ Name = "ComputerName" ; ValidatePattern = "VDI\d+" }}, ` @{ Name = 'Restart-Service' ; Parameters = @{ Name = 'Name' ; ValidateSet = 'Dns', 'Spooler' }} FunctionDefinitions = @{ Name = 'Get-UserInfo' ; ScriptBlock = {$PSSenderInfo}} VisibleExternalCommands = "C:\Windows\System32\WhoAmI.exe" } New-PSRoleCapabilityFile @MaintenanceRoleCapabilityCreationParams Start-Process -FilePath $MaintenanceRoleCapPath #endregion #region 5. Eine Sitzungskonfigurationsdatei (PowerShell Session Configuration File (.PSSC)) erstellen # TODO siehe JEA-Sitzungskonfigurationen (https://docs.microsoft.com/de-de/powershell/scripting/learn/remoting/jea/session-configurations?view=powershell-7) $SessionConfigurationsPath = Join-Path -Path $env:ProgramData -ChildPath "JEASessionConfigurations" New-Item -ItemType Directory -Path $SessionConfigurationsPath $JEADemoSessionPath = Join-Path -Path $SessionConfigurationsPath -ChildPath "JEADemoSession.pssc" $JEAConfigParams = @{ Path = $JEADemoSessionPath Author = "Attila Krick" CompanyName = "attilakrick.com" SessionType = "Default" # ! PROBLEM: "RestrictedRemoteServer" RunAsVirtualAccount = $true TranscriptDirectory = Join-Path -Path $SessionConfigurationsPath -ChildPath "Transcripts" RoleDefinitions = @{ $MaintenanceGroup = @{RoleCapabilities = 'Maintenance'}} Full = $true } New-PSSessionConfigurationFile @JEAConfigParams Test-PSSessionConfigurationFile -Path $JEADemoSessionPath Start-Process -FilePath $JEADemoSessionPath #endregion #region 6. Die Sitzungskonfiguration registrieren # TODO siehe Registrieren von JEA-Konfigurationen (https://docs.microsoft.com/de-de/powershell/scripting/learn/remoting/jea/register-jea?view=powershell-7) # ? Übersicht der registrierten Sitzungskonfigurationen: Get-PSSessionConfiguration | Select-Object Name, Permission $SessionConfigName = "JEA_Demo" Register-PSSessionConfiguration -Name $SessionConfigName -Path $JEADemoSessionPath -Force Restart-Service WinRM #endregion #region 7. JEA als Bediener/Verwalter verwenden # TODO siehe Verwenden von JEA (https://docs.microsoft.com/de-de/powershell/scripting/learn/remoting/jea/using-jea?view=powershell-7) Get-PSSessionCapability -ConfigurationName $SessionConfigName -Username "Domain\$noAdminUser" -Full $cred = Get-Credential -UserName "$noAdminUser" -Message "Credential für localhost" Enter-PSSession -ComputerName "localhost" -Credential $cred # ! Nicht erlaubt Enter-PSSession -ComputerName "localhost" -ConfigurationName "JEA_Demo" -Credential $cred # * Erlaubt C:\Windows\System32\WhoAmI.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 #endregion #region 8. Konfiguration rückgängig machen Unregister-PSSessionConfiguration -Name $SessionConfigName Remove-Item -Path $sessionConfigurationsPath -Recurse -Force Remove-Item -Path $modulePath -Recurse -Force Remove-LocalUser -Name $noAdminUser Remove-LocalGroup -Name $MaintenanceGroup Set-Item -Path "WSMan:\localhost\Client\TrustedHosts" -Value ([String]::Empty) -Force Disable-PSRemoting -Force Get-NetAdapter -Physical | Set-NetConnectionProfile -NetworkCategory "Public" #endregion #endregion |