Podpisywanie skryptów PowerShell
I ❤️ PowerShell. To naprawdę przydatne narzędzie do automatyzacji zadań, które wykonujesz wielokrotnie. Ale może też być wielką dziurą w zabezpieczeniach, jeśli mu na to pozwolisz.
PowerShell pozwala na administrowanie prawie wszystkim na maszynie, więc istnieje wiele szkód, które mogą być wyrządzone przez kogoś, kto jest w stanie uruchomić złośliwe skrypty w twoim środowisku.
Poprzednio ograniczony tylko do systemu Windows, od wersji 6, a teraz z wydaniem PowerShell 7.0, może być również wdrożony w systemach Linux i MacOS. Jednak ten artykuł mówi o Politykach Wykonania, które nie mogą być zmienione w środowiskach innych niż Windows, więc nie przyniosą żadnych korzyści użytkownikom Linux/MacOS (przepraszam).
Polityki Wykonania
Jednym ze sposobów ograniczenia możliwości uruchamiania skryptów w środowiskach Windows jest użycie polityk wykonania PowerShella. Tldr polega na tym, że mogą one być użyte do ograniczenia skryptów, które będą uruchamiane w środowisku. Dostępne opcje od najmniej bezpiecznej do najbardziej bezpiecznej to:
Bypass
Nic nie jest blokowane.
Unrestricted (Zawsze ma zastosowanie na maszynach innych niż Windows)
Tak samo jak ByPass
, ale monituje użytkownika przed uruchomieniem skryptów z Internetu.
RemoteSigned (domyślnie dla serwerów Windows)
Skrypty, które zostały pobrane z Internetu mogą być uruchamiane tylko wtedy, gdy są podpisane. Skrypty napisane na komputerze mogą być uruchamiane
AllSigned
Wszystkie skrypty muszą być podpisane zanim zostaną uruchomione
Restricted (domyślnie dla klientów Windows)
Zapobiega uruchamianiu skryptów. Można uruchamiać tylko pojedyncze polecenia.
Uruchamianie skryptów
Więc chcesz uruchomić własne skrypty PowerShell na swoim serwerze. Ale dostajesz PSSecurityException
jak poniżej.
PS C:\Users\Administrator\Downloads> .\wibble.ps1.\wibble.ps1 : File .\wibble.ps1 cannot be loaded. The file.\wibble.ps1 is not digitally signed. You cannot run this script on the current system.For more information about running scripts and setting execution policy, see about_Execution_Policies athttp://go.microsoft.com/fwlink/?LinkID=135170.At line:1 char:1+ .\wibble.ps1+ ~~~~~~~~~~~~ + CategoryInfo : SecurityError: (:) , PSSecurityException + FullyQualifiedErrorId : UnauthorizedAccess
Jednym ze sposobów rozwiązania tego problemu jest zmiana polityki wykonywania za pomocą polecenia Set-ExecutionPolicy
i zmniejszenie bezpieczeństwa maszyny. Jest to generalnie zły pomysł.
Personalnie, nigdy nie użyłbym niczego mniej bezpiecznego niż RemoteSigned
na serwerze, ale AllSigned
idealnie.
Co to jest podpis skryptu?
Prawdopodobnie chcesz utrzymać bezpieczeństwo maszyny i nie otwierać luk w zabezpieczeniach, więc opcja, która ci pozostała to podpisywanie skryptów.
Podpisanie skryptu oznacza, że ktoś z dostępem do klucza prywatnego dla certyfikatu podpisywania kodu dodał blok podpisu na końcu pliku skryptu.
function Get-Wibble { return "Wibble"}# SIG # Begin signature block# vpnIUpm2XxLRhU1no0iuA62xKxYzR6m95z9Ax21ppeTC9NoRd8ocoSGr1zAd# qlMOlz4lZoVWR4ZmtdCgzde1dVxzv4jjHb6ziDiY2o05UXswD2bl6XaOrUpd# Li0Qjg3d3y2r1nrpO8hos906bgXQswysvouegUJcpt8ftmqBKfEYNeBgnBFm# SIG # End signature block
(tylko przykład. Blok podpisu jest zwykle znacznie dłuższy)
Blok podpisu będzie zawierał skrót skryptu, który został zaszyfrowany przy użyciu klucza prywatnego. Przy próbie uruchomienia skryptu jest on odszyfrowywany przy użyciu klucza publicznego i porównywany z aktualnym skrótem. Jeśli się zgadza, możemy potwierdzić, że skrypt nie został naruszony, ponieważ hash zmieniłby się tak szybko, jak to się stało.
Certyfikaty samopodpisujące
Jeśli Twoje skrypty będą uruchamiane tylko przez maszyny w Twojej organizacji, najprawdopodobniej będziesz w stanie samodzielnie podpisać certyfikaty. Alternatywą jest wydawanie $$$ i kupowanie certyfikatu podpisywania kodu co roku.
Samodzielne podpisywanie oznacza, że sam wygenerujesz certyfikat i podpiszesz nim skrypty.
Jak stworzyć certyfikat samopodpisujący
PowerShell posiada bardzo użyteczne polecenie New-SelfSignedCertificate
do tworzenia certyfikatów samopodpisujących. Możemy je następnie wyeksportować i umieścić w różnych sklepach.
Domyślnie polecenie tworzy certyfikat, który wygasa po 1 roku. Możesz to zmienić, używając parametru -NotAfter
i podając w nim datę, którą chcesz, aby certyfikat wygasł.
Aby utworzyć certyfikat, uruchom sesję PowerShell i wykonaj następujące polecenia
$CertificateName = Read-Host "Input your certificate name"$OutputPFXPath = "$CertificateName.pfx"$OutputCERPath = "$CertificateName.cer"$Password = Get-Credential -UserName Certificate -Message "Enter a secure password:"$certificate = New-SelfSignedCertificate -subject $CertificateName -Type CodeSigning -CertStoreLocation "cert:\CurrentUser\My"$pfxCertificate = Export-PfxCertificate $certificate -FilePath $OutputPFXPath -password $Password.passwordExport-Certificate -Cert $certificate -FilePath $OutputCERPathImport-PfxCertificate $pfxCertificate -CertStoreLocation cert:\CurrentUser\Root -Password $password.passwordWrite-Output "Private Certificate '$CertificateName' exported to $OutputPFXPath"Write-Output "Public Certificate '$CertificateName' exported to $OutputCERPath"
To utworzy certyfikat i wyeksportuje go do dwóch oddzielnych plików z rozszerzeniami .pfx
i .cer
.
PFX
Certyfikat PFX jest tym, który będzie musiał być zainstalowany na maszynach, które będą podpisywać. W naszym przypadku jest to każdy z naszych deweloperów.
Powinien on być zainstalowany w sklepie cert:\CurrentUser\Root
, znanym również jako sklep „Trusted Root Certification Authorities”.
Plik ten powinien być przechowywany w bezpiecznym miejscu. Hasło powinno być zabezpieczone oddzielnie (należy użyć menedżera haseł). Jeśli zły aktor wejdzie w posiadanie obu tych plików, będzie mógł podpisać swoje złośliwe skrypty tak, jakby był Tobą.
CER
Plik certyfikatu CER jest tym, co będziesz musiał zainstalować na maszynach, na których będą uruchamiane skrypty. Jego instalacja nie wymaga podania hasła, ale nie może być użyty do podpisywania skryptów. Zawiera on tylko klucz publiczny używany do odszyfrowania podpisu.
Ponieważ nie zawiera klucza prywatnego, ten certyfikat może być swobodnie dystrybuowany do wszystkich środowisk, które będą uruchamiać skrypty.
Trzeba go zainstalować w dwóch magazynach certyfikatów na maszynach, które będą uruchamiać skrypty; magazynach cert:\LocalMachine\Root
i cert:\LocalMachine\TrustedPublisher
.
Podpisywanie skryptu
Funkcja Set-AuthenticodeSignature
jest dostarczana do podpisywania skryptów. Musimy przekazać ścieżkę do skryptu oraz certyfikat z magazynu. Napisaliśmy funkcję wrapper, która może podpisywać skrypty.
function Set-ScriptSignatures { param ( $pathToScripts = "." ) $certificateName = "PowerShell Signing Certificate" $scripts = Get-ChildItem -Path "$pathToScripts\*" -Include *.ps1, *.psm1 -Recurse $certificate = @(Get-ChildItem cert:\CurrentUser\My -codesign | Where-Object { $_.issuer -like "*$certificateName*" } ) foreach ($script in $scripts) { Write-Host "Signing $script" Set-AuthenticodeSignature $script -Certificate $certificate }}
Zmienna $certificateName
powinna zawierać nazwę użytą podczas tworzenia certyfikatu.
Możesz użyć funkcji, podając ścieżkę do katalogu zawierającego skrypty, a ona zapętli je podpisując wszystkie.
Po zainstalowaniu skryptów na maszynie docelowej powinieneś być teraz w stanie uruchomić skrypty bez żadnych problemów.