Перетворіть захищений рядок у звичайний текст


87

Я працюю в PowerShell і маю код, який успішно перетворює введений користувачем пароль у звичайний текст:

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

Я пробував кілька способів повернути його назад, але, здається, жоден з них не працює належним чином. Зовсім недавно я пробував із наступним:

$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

Це також дає мені помилку.

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

Хтось знає спосіб, який буде працювати для цього?

Відповіді:


115

Ви близькі, але параметром, якому ви передаєте, SecureStringToBSTRмає бути a SecureString. Здається, ви передаєте результат ConvertFrom-SecureString, який є зашифрованим стандартним рядком. Тож зверніться ConvertTo-SecureStringдо цього, перш ніж переходити до SecureStringToBSTR.

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

4
Я радий, що це працює. Будьте обережні зі своїм рядком, зараз це незахищена змінна рядка, що містить, мабуть, щось важливе, наприклад, пароль - він більше не захищений у вашій пам’яті процесу тощо
MatthewG

19
Відповідно до документації Marshal.SecureStringToBSTR : Оскільки цей метод виділяє некеровану пам’ять, необхідну для рядка, завжди звільняйте BSTR після закінчення, викликаючи метод ZeroFreeBSTR . Таким чином, ви повинні виконати наступні дії в кінці кінців: [Runtime.InteropServices.Marshal]::ZeroFreeBSTR($BSTR).
Росберг Лінхарес

@RosbergLinhares - Оскільки ми (мабуть) зосереджені на PowerShell, чи є якась причина, чому ви не могли просто $BSTR = $null?
Орангутех

3
@Orangutech Ви не можете встановити для змінної лише значення $null, оскільки тут ми маємо справу з некерованими об'єктами. Ви не отримаєте помилку відразу, але я думаю, що у вас можуть виникнути проблеми з часом.
Rosberg Linhares

1
Окрім витоку пам'яті, спричиненого відсутнім закликом до ZeroFreeBSTR(), як уже зазначалося, використання PtrToStringAuto()завжди було концептуально недоліком, і - тепер, коли PowerShell є крос-платформенним - не працює на Unix-подібних платформах. Це повинно було бути завжди PtrToStringBSTR() - див. Цю відповідь .
mklement0

81

Ви також можете використовувати PSCredential.GetNetworkCredential ():

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

Я протестував обидва методи, і обидва вони все ще правильні.
Максиміліан Бурслі

10
Проголосував за це рішення, оскільки воно більше Powershelly.
Джим,

1
Використовуйте System.Management.Automation.PSCredentialу старих версіях PS, коли коротке ім’я типу не розпізнається.
marsze

1
Коротше:[PSCredential]::new(0, $SecurePassword).GetNetworkCredential().Password
majkinetor

Коротше:[System.Net.NetworkCredential]::new("", $SecurePassword).Password
К. Франк

36

Найпростіший спосіб перетворити його назад у PowerShell

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

1
Справді, немає необхідності проходити через PSCredential.
Ніколас

Мені подобається такий підхід. FYI для наркоманів сумісності, це перевантаження конструктора SecureStringбуло введено в .Net Framework 4.0. На PowerShell v2 я намагався, (New-Object -TypeName System.Net.NetworkCredential -ArgumentList "u",$SecureString).Passwordале, на жаль SecureString, мовчки перетворюється на String. Здається, виклик вдався, але Passwordвластивістю тоді є буквальне значення "System.Security.SecureString". Будь обережний.
Джон Різ,

17

У PS 7 ви можете використовувати ConvertFrom-SecureStringта -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
Це зводило мене з розуму. Я намагався використати цей синтаксис у v5 безрезультатно.
Тоні
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.