Konvertieren Sie eine sichere Zeichenfolge in einfachen Text

87

Ich arbeite in PowerShell und habe Code, der ein vom Benutzer eingegebenes Kennwort erfolgreich in Klartext konvertiert:

$SecurePassword = Read-Host -AsSecureString  "Enter password" | convertfrom-securestring | out-file C:\Users\tmarsh\Documents\securePassword.txt

Ich habe verschiedene Möglichkeiten ausprobiert, um es zurück zu konvertieren, aber keine davon scheint richtig zu funktionieren. Zuletzt habe ich Folgendes versucht:

$PlainPassword = Get-Content C:\Users\tmarsh\Documents\securePassword.txt

#convert the SecureString object to plain text using PtrToString and SecureStringToBSTR
$BSTR = [System.Runtime.InteropServices.Marshal]::SecureStringToBSTR($PlainPassword)
$PlainPassword = [System.Runtime.InteropServices.Marshal]::PtrToStringAuto($BSTR)
[Runtime.InteropServices.Marshal]::ZeroFreeBSTR($BSTR) #this is an important step to keep things secure

Dies gibt mir auch einen Fehler.

Cannot convert argument "s", with value: "01000000d08c9ddf0115d1118c7a00c04fc297eb0100000026a5b6067d53fd43801a9ef3f8ef9e43000000000200000000000366000
0c0000000100000008118fdea02bfb57d0dda41f9748a05f10000000004800000a000000010000000c50f5093f3b87fbf9ee57cbd17267e0a10000000833d1d712cef01497872a3457bc8
bc271400000038c731cb8c47219399e4265515e9569438d8e8ed", for "SecureStringToBSTR" to type "System.Security.SecureString": "Cannot convert the "01000000
d08c9ddf0115d1118c7a00c04fc297eb0100000026a5b6067d53fd43801a9ef3f8ef9e430000000002000000000003660000c0000000100000008118fdea02bfb57d0dda41f9748a05f10
000000004800000a000000010000000c50f5093f3b87fbf9ee57cbd17267e0a10000000833d1d712cef01497872a3457bc8bc271400000038c731cb8c47219399e4265515e9569438d8e8
ed" value of type "System.String" to type "System.Security.SecureString"."
At C:\Users\tmarsh\Documents\Scripts\Local Admin Script\PlainTextConverter1.ps1:14 char:1
+ $BSTR = [System.Runtime.InteropServices.Marshal]::SecureStringToBSTR($PlainPassw ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : NotSpecified: (:) [], MethodException
    + FullyQualifiedErrorId : MethodArgumentConversionInvalidCastArgument

Cannot find an overload for "PtrToStringAuto" and the argument count: "1".
At C:\Users\tmarsh\Documents\Scripts\Local Admin Script\PlainTextConverter1.ps1:15 char:1
+ $PlainPassword = [System.Runtime.InteropServices.Marshal]::PtrToStringAuto($BSTR ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : NotSpecified: (:) [], MethodException
    + FullyQualifiedErrorId : MethodCountCouldNotFindBest

Cannot convert argument "s", with value: "", for "ZeroFreeBSTR" to type "System.IntPtr": "Cannot convert null to type "System.IntPtr"."
At C:\Users\tmarsh\Documents\Scripts\Local Admin Script\PlainTextConverter1.ps1:16 char:1
+ [Runtime.InteropServices.Marshal]::ZeroFreeBSTR($BSTR) #this is an important ste ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : NotSpecified: (:) [], MethodException
    + FullyQualifiedErrorId : MethodArgumentConversionInvalidCastArgument

Password is:  01000000d08c9ddf0115d1118c7a00c04fc297eb0100000026a5b6067d53fd43801a9ef3f8ef9e430000000002000000000003660000c0000000100000008118fdea02bfb57d0dda41f97
48a05f10000000004800000a000000010000000c50f5093f3b87fbf9ee57cbd17267e0a10000000833d1d712cef01497872a3457bc8bc271400000038c731cb8c47219399e4265515e9569
438d8e8ed

Kennt jemand einen Weg, der dafür funktioniert?

tmarsh
quelle

Antworten:

115

Sie sind nah dran, aber der Parameter, an den Sie übergeben, SecureStringToBSTRmuss a sein SecureString. Sie scheinen das Ergebnis von zu übergeben ConvertFrom-SecureString, bei dem es sich um eine verschlüsselte Standardzeichenfolge handelt. Rufen Sie ConvertTo-SecureStringdies an, bevor Sie zu SecureStringToBSTR.

$SecurePassword = ConvertTo-SecureString $PlainPassword -AsPlainText -Force
$BSTR = [System.Runtime.InteropServices.Marshal]::SecureStringToBSTR($SecurePassword)
$UnsecurePassword = [System.Runtime.InteropServices.Marshal]::PtrToStringAuto($BSTR)
MatthewG
quelle
4
Ich bin froh, dass es funktioniert. Seien Sie vorsichtig mit Ihrer Zeichenfolge, jetzt ist es eine ungesicherte Zeichenfolgenvariable, die vermutlich etwas Wichtiges wie ein Passwort enthält - sie ist nicht mehr sicher in Ihrem Prozessspeicher usw.
MatthewG
19
Gemäß der Dokumentation zu Marshal.SecureStringToBSTR : Da diese Methode den für eine Zeichenfolge erforderlichen nicht verwalteten Speicher zuweist, geben Sie den BSTR immer frei, wenn Sie mit dem Aufrufen der ZeroFreeBSTR-Methode fertig sind . Am Ende müssen Sie also Folgendes ausführen : [Runtime.InteropServices.Marshal]::ZeroFreeBSTR($BSTR).
Rosberg Linhares
@RosbergLinhares - Da wir (vermutlich) auf Powershell fokussiert sind, gibt es einen Grund, warum Sie das nicht einfach können $BSTR = $null?
Orangutech
3
@Orangutech Sie können die Variable nicht nur auf setzen $null, da es sich hier um nicht verwaltete Objekte handelt. Sie werden nicht sofort einen Fehler erhalten, aber ich denke, dass Sie im Laufe der Zeit Probleme haben können.
Rosberg Linhares
1
Abgesehen von dem Speicherverlust, der sich aus dem fehlenden Aufruf ZeroFreeBSTR()von PtrToStringAuto()ergab , war die Verwendung von, wie bereits erwähnt, immer konzeptionell fehlerhaft und schlägt - jetzt, da PowerShell plattformübergreifend ist - auf Unix-ähnlichen Plattformen fehl. Es hätte immer so sein sollen PtrToStringBSTR() - siehe diese Antwort .
mklement0
81

Sie können auch PSCredential.GetNetworkCredential () verwenden:

$SecurePassword = Get-Content C:\Users\tmarsh\Documents\securePassword.txt | ConvertTo-SecureString
$UnsecurePassword = (New-Object PSCredential "user",$SecurePassword).GetNetworkCredential().Password
Nicolas Melay
quelle
Ich habe beide Methoden getestet und beide sind immer noch korrekt.
Maximilian Burszley
10
Diese Lösung wurde verbessert, weil sie mehr Powershelly ist.
Jim
1
Verwendung System.Management.Automation.PSCredentialin älteren PS-Versionen, wenn der Kurztypname nicht erkannt wird.
Marsze
1
Kürzere:[PSCredential]::new(0, $SecurePassword).GetNetworkCredential().Password
Majkinetor
Kürzere:[System.Net.NetworkCredential]::new("", $SecurePassword).Password
K. Frank
36

Der einfachste Weg, es in PowerShell zurück zu konvertieren

[System.Net.NetworkCredential]::new("", $SecurePassword).Password
Vladimir Zelenov
quelle
1
In der Tat besteht keine Notwendigkeit, PSCredential zu durchlaufen.
Nicolas Melay
Ich mag diesen Ansatz. Zu Ihrer Information für Kompatibilitäts-Junkies wurde diese Konstruktorüberlastung SecureStringin .Net Framework 4.0 eingeführt. Auf PowerShell v2 habe ich es versucht, (New-Object -TypeName System.Net.NetworkCredential -ArgumentList "u",$SecureString).Passwordaber leider wird das SecureStringstillschweigend in ein konvertiert String. Der Aufruf scheint erfolgreich zu sein, aber die PasswordEigenschaft ist dann der Literalwert "System.Security.SecureString". Achtung.
John Rees
17

In PS 7 können Sie verwenden , ConvertFrom-SecureStringund -AsPlainText:

 $UnsecurePassword = ConvertFrom-SecureString -SecureString $SecurePassword -AsPlainText

https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell.security/ConvertFrom-SecureString?view=powershell-7#parameters

ConvertFrom-SecureString
           [-SecureString] <SecureString>
           [-AsPlainText]
           [<CommonParameters>]
Macke
quelle
3
Das hat mich verrückt gemacht. Ich habe versucht, diese Syntax in Version 5 ohne Erfolg zu verwenden.
Tony