Converti una stringa protetta in testo normale


90

Sto lavorando in PowerShell e ho un codice che converte correttamente la password inserita da un utente in testo normale:

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

Ho provato diversi modi per riconvertirlo, ma nessuno di loro sembra funzionare correttamente. Più di recente, ho provato con quanto segue:

$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

Anche questo mi dà un errore.

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

Qualcuno sa di un modo che funzionerà per questo?

Risposte:


117

Sei vicino, ma il parametro a cui passi SecureStringToBSTRdeve essere un SecureString. Sembra che tu stia passando il risultato di ConvertFrom-SecureString, che è una stringa standard crittografata. Quindi chiama ConvertTo-SecureStringquesto prima di passare a SecureStringToBSTR.

$SecurePassword = ConvertTo-SecureString $PlainPassword -AsPlainText -Force
$BSTR = [System.Runtime.InteropServices.Marshal]::SecureStringToBSTR($SecurePassword)
$UnsecurePassword = [System.Runtime.InteropServices.Marshal]::PtrToStringAuto($BSTR)

4
Sono contento che funzioni. Fai attenzione alla tua stringa, ora, è una variabile di stringa non protetta che contiene presumibilmente qualcosa di importante come una password - non è più protetta nella memoria del tuo processo, ecc.
MatthewG

19
Secondo la documentazione Marshal.SecureStringToBSTR : poiché questo metodo alloca la memoria non gestita richiesta per una stringa, al termine liberare sempre il BSTR chiamando il metodo ZeroFreeBSTR . Quindi, è necessario eseguire il seguente alla fine: [Runtime.InteropServices.Marshal]::ZeroFreeBSTR($BSTR).
Rosberg Linhares

@RosbergLinhares - Dato che siamo (presumibilmente) focalizzati su PowerShell, c'è qualche motivo per cui non potresti semplicemente $BSTR = $null?
Orangutech

3
@Orangutech Non puoi solo impostare la variabile su $null, perché qui abbiamo a che fare con oggetti non gestiti. Non riceverai un errore immediatamente, ma penso che potresti avere problemi con il passare del tempo.
Rosberg Linhares

1
A parte la perdita di memoria derivante dalla chiamata mancante ZeroFreeBSTR(), come affermato, l'uso di PtrToStringAuto()è sempre stato concettualmente imperfetto e, ora che PowerShell è multipiattaforma, fallisce su piattaforme simili a Unix. Dovrebbe essere sempre stato PtrToStringBSTR() - vedi questa risposta .
mklement0

84

Puoi anche utilizzare PSCredential.GetNetworkCredential ():

$SecurePassword = Get-Content C:\Users\tmarsh\Documents\securePassword.txt | ConvertTo-SecureString
$UnsecurePassword = (New-Object PSCredential "user",$SecurePassword).GetNetworkCredential().Password

Ho testato entrambi i metodi e sono entrambi ancora corretti.
Maximilian Burszley

10
Votato questa soluzione perché è più Powershelly.
Jim il

1
Utilizzare System.Management.Automation.PSCredentialnelle versioni precedenti di PS quando il nome del tipo breve non viene riconosciuto.
marsze

1
Più breve:[PSCredential]::new(0, $SecurePassword).GetNetworkCredential().Password
majkinetor

Più breve:[System.Net.NetworkCredential]::new("", $SecurePassword).Password
K. Frank

37

Il modo più semplice per riconvertirlo in PowerShell

[System.Net.NetworkCredential]::new("", $SecurePassword).Password

1
In effetti, non è necessario passare attraverso PSCredential.
Nicolas Melay

Mi piace questo approccio. Cordiali saluti per i drogati di compatibilità, questa presa di sovraccarico del costruttore è SecureStringstata introdotta in .Net Framework 4.0. Su PowerShell v2 ho provato (New-Object -TypeName System.Net.NetworkCredential -ArgumentList "u",$SecureString).Passwordma sfortunatamente il file SecureStringviene convertito silenziosamente in un file String. La chiamata sembra riuscire, ma la Passwordproprietà è quindi il valore letterale "System.Security.SecureString". Stai attento.
John Rees,

19

In PS 7, puoi usare ConvertFrom-SecureStringe -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>]

3
Questo mi stava facendo impazzire. Stavo cercando di utilizzare questa sintassi in v5 senza alcun risultato.
Tony
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.