PowerShell/05advanced12 min

Bezpieczeństwo: credentiale, SecureString, brak haseł w kodzie

Probe'y ZEUS łączą się z kontrolerami domeny i zdalnymi maszynami — operują na wrażliwych poświadczeniach. W produkcie bezpieczeństwa nasze własne skrypty muszą być wzorem: żadnych haseł w kodzie, poświadczenia jako PSCredential.

Nigdy haseł w skrypcie

Hasło w kodzie trafia do repozytorium, logów i historii git na zawsze.

# źle — hasło w kodzie, wyciek na zawsze
$pass = "P@ssw0rd123"
$cred = New-Object PSCredential("corp\svc", (ConvertTo-SecureString $pass -AsPlainText -Force))

# dobrze — poświadczenia podane z zewnątrz jako parametr
param([Parameter(Mandatory)][pscredential]$Credential)

Standard ProfessNet: skrypt probe nie zawiera żadnego hasła ani tokenu. Poświadczenia przyjmuje jako parametr [pscredential] albo pobiera z bezpiecznego magazynu. Plain-text password w kodzie = krytyczny błąd review.

PSCredential — standardowy typ poświadczeń

PSCredential przechowuje nazwę użytkownika i hasło jako SecureString. Wszystkie cmdlety zdalne (Invoke-Command, New-PSSession) przyjmują go przez -Credential.

[CmdletBinding()]
param(
    [Parameter(Mandatory)][string]$ComputerName,
    [Parameter(Mandatory)][pscredential]$Credential
)

Invoke-Command -ComputerName $ComputerName -Credential $Credential -ScriptBlock {
    Get-Service
}

Interaktywnie poświadczenia pobieramy bezpiecznie przez Get-Credential:

$cred = Get-Credential -UserName "corp\svc-zeus" -Message "Poświadczenia probe"

SecureString — czemu nie zwykły string

SecureString trzyma dane zaszyfrowane w pamięci i pozwala je wymazać. Nie pojawia się przypadkiem w logach ani transkrypcji.

# konwersja, gdy naprawdę trzeba (np. do API wymagającego plain)
$plain = $Credential.GetNetworkCredential().Password   # użyj i od razu wyczyść

Standard ProfessNet: plain-text z SecureString wyciągamy tylko w momencie użycia (na granicy z API, które inaczej nie potrafi) i nie przechowujemy go w zmiennej dłużej niż to konieczne. Nigdy nie logujemy tej wartości.

Magazyn poświadczeń — SecretManagement

Do trwałego przechowywania używamy modułu Microsoft.PowerShell.SecretManagement z vaultem (np. Windows Credential Manager), a nie plików.

# zapis raz, poza kodem
Set-Secret -Name "ZeusProbeCred" -Secret $cred

# odczyt w skrypcie — brak hasła w kodzie
$cred = Get-Secret -Name "ZeusProbeCred"

Wykonanie zdalne i WinRM

Połączenia zdalne idą przez WinRM z poświadczeniami i, gdzie to możliwe, po szyfrowanym transporcie.

$session = New-PSSession -ComputerName $dc -Credential $Credential -UseSSL
try {
    Invoke-Command -Session $session -ScriptBlock { Get-ADForest }
}
finally {
    Remove-PSSession $session
}
ZasadaRealizacja
Brak haseł w kodzieparametr [pscredential] lub SecretManagement
Bezpieczne hasło w pamięciSecureString / PSCredential
Pobranie interaktywneGet-Credential
Trwałe poświadczeniaGet-Secret / Set-Secret (vault)
Brak wycieku do logównie logujemy hasła, sprzątamy sesje

Wskazówka: wyłącz transkrypcję wrażliwych fragmentów i pamiętaj, że ConvertTo-SecureString ... -AsPlainText w kodzie to czerwona flaga — oznacza, że plain-text jest gdzieś w skrypcie.


Poświadczenia jako PSCredential, sekrety w vaultcie, plain-text tylko na moment użycia i nigdy w repo. W probe'ach ZEUS bezpieczeństwo poświadczeń to nie dodatek — to definicja poprawnie napisanego skryptu.