Convertir une chaîne sécurisée en texte brut

87

Je travaille dans PowerShell et j'ai un code qui convertit avec succès un mot de passe saisi par l'utilisateur en texte brut:

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

J'ai essayé plusieurs façons de le reconvertir, mais aucune d'entre elles ne semble fonctionner correctement. Plus récemment, j'ai essayé ce qui suit:

$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

Cela me donne également une erreur.

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

Quelqu'un connaît-il un moyen qui fonctionnera pour cela?

tmarsh
la source

Réponses:

115

Vous êtes proche, mais le paramètre que vous passez SecureStringToBSTRdoit être un SecureString. Vous semblez transmettre le résultat de ConvertFrom-SecureString, qui est une chaîne standard chiffrée. Alors appelez ConvertTo-SecureStringceci avant de passer à SecureStringToBSTR.

$SecurePassword = ConvertTo-SecureString $PlainPassword -AsPlainText -Force
$BSTR = [System.Runtime.InteropServices.Marshal]::SecureStringToBSTR($SecurePassword)
$UnsecurePassword = [System.Runtime.InteropServices.Marshal]::PtrToStringAuto($BSTR)
MatthewG
la source
4
Je suis content que ça marche. Faites attention avec votre chaîne, maintenant, il s'agit d'une variable de chaîne non sécurisée contenant probablement quelque chose d'important comme un mot de passe - il n'est plus sécurisé dans la mémoire de votre processus, etc.
MatthewG
19
Selon la documentation Marshal.SecureStringToBSTR : Étant donné que cette méthode alloue la mémoire non managée requise pour une chaîne, libérez toujours le BSTR lorsque vous avez terminé en appelant la méthode ZeroFreeBSTR . Donc, vous devez d'exécuter ce qui suit à la fin: [Runtime.InteropServices.Marshal]::ZeroFreeBSTR($BSTR).
Rosberg Linhares
@RosbergLinhares - Puisque nous sommes (vraisemblablement) concentrés sur PowerShell, y a-t-il une raison pour laquelle vous ne pouvez pas simplement $BSTR = $null?
Orangutech
3
@Orangutech Vous ne pouvez pas seulement définir la variable sur $null, car nous traitons ici d'objets non gérés. Vous n'obtiendrez pas d'erreur immédiatement, mais je pense que vous pourriez avoir des problèmes avec le temps.
Rosberg Linhares
1
Mis à part la fuite de mémoire résultant de l'appel manquant à ZeroFreeBSTR(), comme indiqué, l'utilisation de PtrToStringAuto()était toujours conceptuellement défectueuse et - maintenant que PowerShell est multiplateforme - échoue sur les plates-formes de type Unix. Cela aurait toujours dû l'être PtrToStringBSTR() - voyez cette réponse .
mklement0
81

Vous pouvez également utiliser PSCredential.GetNetworkCredential ():

$SecurePassword = Get-Content C:\Users\tmarsh\Documents\securePassword.txt | ConvertTo-SecureString
$UnsecurePassword = (New-Object PSCredential "user",$SecurePassword).GetNetworkCredential().Password
Nicolas Melay
la source
J'ai testé les deux méthodes et elles sont toutes les deux toujours correctes.
Maximilian Burszley
10
J'ai voté pour cette solution car elle est plus Powershelly.
Jim
1
À utiliser System.Management.Automation.PSCredentialdans les anciennes versions PS lorsque le nom de type court n'est pas reconnu.
marsze
1
Shorter:[PSCredential]::new(0, $SecurePassword).GetNetworkCredential().Password
majkinetor
Plus court:[System.Net.NetworkCredential]::new("", $SecurePassword).Password
K. Frank
36

Le moyen le plus simple de le reconvertir dans PowerShell

[System.Net.NetworkCredential]::new("", $SecurePassword).Password
Vladimir Zelenov
la source
1
En effet, pas besoin de passer par PSCredential.
Nicolas Melay
J'aime cette approche. Pour info pour les accros de compatibilité, cette prise de surcharge de constructeur a SecureStringété introduite dans .Net Framework 4.0. Sur PowerShell v2, j'ai essayé (New-Object -TypeName System.Net.NetworkCredential -ArgumentList "u",$SecureString).Passwordmais malheureusement, le SecureStringest silencieusement converti en String. L'appel semble réussir, mais la Passwordpropriété est alors la valeur littérale "System.Security.SecureString". Faites attention.
John Rees le
17

Dans PS 7, vous pouvez utiliser ConvertFrom-SecureStringet -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
la source
3
Cela me rendait fou. J'essayais d'utiliser cette syntaxe dans la v5 en vain.
Tony