Converta uma string segura em texto simples


87

Estou trabalhando no PowerShell e tenho um código que converte com êxito uma senha inserida pelo usuário em texto simples:

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

Tentei várias maneiras de convertê-lo de volta, mas nenhuma delas parece funcionar corretamente. Mais recentemente, tentei o seguinte:

$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

Isso também me dá um erro.

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

Alguém conhece uma maneira que funcione para isso?

Respostas:


115

Você está perto, mas o parâmetro que você passa SecureStringToBSTRdeve ser a SecureString. Você parece estar passando o resultado de ConvertFrom-SecureString, que é uma string padrão criptografada. Portanto, ligue ConvertTo-SecureStringantes de passar para SecureStringToBSTR.

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

4
Estou feliz que funcione. Tenha cuidado com sua string, agora, ela é uma variável de string insegura contendo provavelmente algo importante como uma senha - ela não é mais segura em sua memória de processo, etc.
— MatthewG

19
De acordo com a documentação Marshal.SecureStringToBSTR : Como esse método aloca a memória não gerenciada necessária para uma string, sempre libere o BSTR quando terminar, chamando o método ZeroFreeBSTR . Então, você tem que executar o seguinte no final: [Runtime.InteropServices.Marshal]::ZeroFreeBSTR($BSTR).
— Rosberg Linhares

@RosbergLinhares - Já que estamos (presumivelmente) focados no PowerShell, há algum motivo para você não poder simplesmente $BSTR = $null?
— Orangutech

3
@Orangutech Você não pode apenas definir a variável como $null, porque aqui estamos lidando com objetos não gerenciados. Você não receberá um erro imediatamente, mas acho que poderá ter problemas com o passar do tempo.
— Rosberg Linhares

1
Além do vazamento de memória resultante da falta de chamada para ZeroFreeBSTR(), conforme declarado, o uso de PtrToStringAuto()sempre foi conceitualmente falho e - agora que o PowerShell é multiplataforma - falha em plataformas do tipo Unix. Sempre deveria ter sido PtrToStringBSTR() - veja esta resposta .
— mklement0

81

Você também pode usar PSCredential.GetNetworkCredential ():

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

Testei os dois métodos e ainda estão corretos.
— Maximilian Burszley

10
Votei esta solução porque é mais Powershelly.
— Jim

1
Use System.Management.Automation.PSCredentialem versões mais antigas do PS quando o nome do tipo abreviado não for reconhecido.
— março

1
Shorter:[PSCredential]::new(0, $SecurePassword).GetNetworkCredential().Password
— majkinetor

Shorter:[System.Net.NetworkCredential]::new("", $SecurePassword).Password
— K. Frank

36

A maneira mais fácil de convertê-lo de volta no PowerShell

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

1
Na verdade, não há necessidade de passar pelo PSCredential.
— Nicolas Melay

Eu gosto dessa abordagem. Para sua informação, para viciados em compatibilidade, essa sobrecarga de construtor SecureStringfoi introduzida no .Net Framework 4.0. No PowerShell v2 eu tentei, (New-Object -TypeName System.Net.NetworkCredential -ArgumentList "u",$SecureString).Passwordmas infelizmente o SecureStringé silenciosamente convertido em um String. A chamada parece ter sucesso, mas a Passwordpropriedade é o valor literal "System.Security.SecureString". Seja cuidadoso.
— John Rees,

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.