(NIE)bezpieczeństwo szyfrowania haseł

Poruszę dziś może i trochę odgrzewany temat, ale niestety czuję że muszę. Piszę to głównie ku przestrodze, gdyż często spotykam się (nawet wśród znajomych) administratorów-skrypciarzy z dość złudnym pojęciem bezpieczeństwa. Mam tutaj na myśli próby szyfrowania danych w PowerShellu, a  w szczególności zapisywania zaszyfrowanych haseł w plikach, tak by np. inny użytkownik mógł wykonać skrypt z uprawnieniami np. administratora nie znając jego hasła.

Jak tego dokonać? Bardzo prosto wystarczy skryptowo stworzyć obiekt typu PSCredential z podaniem jako atrybuty użytkownika i hasło, jak np.:

$password = ConvertTo-SecureString "P@ssw0rd" -AsPlainText -Force
$username = "domain\username"
$cred = New-Object System.Management.Automation.PSCredential $Username, $Password
$cred

Jak widzimy posiadamy obiekt PSCredential. Jednakże dość bolesne jest to, iż jesteśmy zmuszeni podawać hasło jawnie. Pewnym wyjściem z tej sytuacji jest właśnie szyfrowanie hasła przy użyciu cmdletów ConvertFrom-SecureString oraz ConvertTo-SecureString, a następnie zapisanie go do pliku.

$cred.Password | ConvertFrom-SecureString | Set-Content "p:\password.txt"

Sam plik owszem posiada zaszyfrowaną treść.

Get-Content "p:\password.txt"

Niemniej jednak jest to dość złudne podejście bezpieczeństwa. Spójrzmy na to od inne strony. Jednakże aby, inny użytkownik mógł wykonać skrypt przy użyciu takowych poświadczeń konieczne jest udostępnienie tego pliku. A co za tym idzie taki użytkownik może rozpocząć proces deszyfrowania hasła, aż do momentu w jakim stanie się ono jawnym tekstem. Ale sprawdźmy to na przykładzie. Najpierw odczytajmy zaszyfrowany plik.

$PasswordFromFile = Get-Content "p:\password.txt"

Następnie przekonwertujmy go na typ SecureString.

$PasswordASSecureString = $PasswordFromFile | ConvertTo-SecureString
$PasswordASSecureString

OK, więc mamy zaszyfrowane hasło w formie SecureString, co może wydawać się idealnym podejściem do sprawy, gdyż nigdzie nie mamy jawnie podawanego hasła. Nic bardziej mylnego, niestety przy wykorzystaniu odpowiednich klas .NET’a możliwe jest przekonwertowanie typu SecureString do formy jawnego tekstu.

[Runtime.InteropServices.Marshal]::PtrToStringAuto([Runtime.InteropServices.Marshal]::SecureStringToBSTR($PasswordASSecureString))

Co tak naprawdę zrobiliśmy. Odczytaliśmy hasło i zapisaliśmy go w pamięci. Metoda SecureStringToBSTR pozwoliła nam na uzyskanie adresu pamięci, w której jest przechowywane nasze hasło. Natomiast metoda PtrToStringAuto umożliwia na sięgnięcie pod odpowiedni adres pamięci i pobranie jej zawartości. W naszym przypadku będzie to wcześniej pobrane hasło zapisane w formie jawnego tekstu.

Dlatego ku przestrodze powtórzę się. Takie szyfrowanie danych przy pomocy PowerShella może i wygląda na dość bezpieczny sposób. Niemniej jednak dla chcącego nic trudnego. Wystarczą tak naprawdę dwie linijki kodu i wszystko staje się jawne.

$PasswordASSecureString = Get-Content "p:\password.txt" | ConvertTo-SecureString
[Runtime.InteropServices.Marshal]::PtrToStringAuto([Runtime.InteropServices.Marshal]::SecureStringToBSTR($PasswordASSecureString))

PS. Alternatywnie takowy SecureString można wykorzystać do stworzenia obiektu PSCredential, który posiada metodę GetNetworkCredential()

$cred = New-Object System.Management.Automation.PSCredential $Username, $PasswordASSecureString
$cred.GetNetworkCredential().Password
Reklamy

Skomentuj

Wprowadź swoje dane lub kliknij jedną z tych ikon, aby się zalogować:

Logo WordPress.com

Komentujesz korzystając z konta WordPress.com. Wyloguj / Zmień )

Zdjęcie z Twittera

Komentujesz korzystając z konta Twitter. Wyloguj / Zmień )

Zdjęcie na Facebooku

Komentujesz korzystając z konta Facebook. Wyloguj / Zmień )

Zdjęcie na Google+

Komentujesz korzystając z konta Google+. Wyloguj / Zmień )

Connecting to %s