แปลงสตริงที่ปลอดภัยเป็นข้อความธรรมดา


90

ฉันทำงานใน 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

ไม่มีใครรู้วิธีที่จะทำงานนี้?

คำตอบ:


117

คุณอยู่ใกล้ แต่พารามิเตอร์ที่คุณส่งผ่านSecureStringToBSTRต้องเป็นไฟล์SecureString. ดูเหมือนว่าคุณจะส่งผ่านผลลัพธ์ConvertFrom-SecureStringซึ่งเป็นสตริงมาตรฐานที่เข้ารหัส ดังนั้นเรียกเกี่ยวกับเรื่องนี้ก่อนที่จะผ่านไปConvertTo-SecureStringSecureStringToBSTR

$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 เมื่อเสร็จสิ้นโดยการเรียกวิธี ดังนั้นคุณต้องดำเนินการต่อไปนี้ในตอนท้าย: [Runtime.InteropServices.Marshal]::ZeroFreeBSTR($BSTR).
Rosberg Linhares

@RosbergLinhares - เนื่องจากเรา (น่าจะ) เน้น powershell มีเหตุผลอะไรที่คุณทำไม่ได้$BSTR = $null?
Orangutech

3
@Orangutech คุณไม่สามารถตั้งค่าตัวแปรเป็น$nullเท่านั้นเพราะที่นี่เรากำลังจัดการกับวัตถุที่ไม่มีการจัดการ คุณจะไม่ได้รับข้อผิดพลาดในทันที แต่ฉันคิดว่าคุณอาจมีปัญหาเมื่อเวลาผ่านไป
Rosberg Linhares

1
นอกเหนือจากการรั่วไหลของหน่วยความจำอันเป็นผลมาจากการโทรที่ขาดหายไปZeroFreeBSTR()ตามที่ระบุไว้การใช้งานPtrToStringAuto()ยังคงมีข้อบกพร่องอยู่เสมอและตอนนี้ PowerShell เป็นข้ามแพลตฟอร์ม - ล้มเหลวบนแพลตฟอร์มที่คล้าย Unix ควรจะเป็นเสมอPtrToStringBSTR() - ดูคำตอบนี้
mklement0

84

คุณยังสามารถใช้ PSCredential.GetNetworkCredential ():

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

ฉันได้ทดสอบทั้งสองวิธีแล้วและทั้งสองยังคงถูกต้อง
Maximilian Burszley

10
โหวตให้โซลูชันนี้เนื่องจากเป็น Powershelly มากกว่า
จิม

1
ใช้System.Management.Automation.PSCredentialใน PS เวอร์ชันเก่าเมื่อไม่รู้จักชื่อประเภทแบบสั้น
มีนาคม

1
สั้นกว่า:[PSCredential]::new(0, $SecurePassword).GetNetworkCredential().Password
majkinetor

สั้นกว่า:[System.Net.NetworkCredential]::new("", $SecurePassword).Password
K. Frank

37

วิธีที่ง่ายที่สุดในการแปลงกลับใน PowerShell

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

1
ไม่จำเป็นต้องผ่าน PSCredential
Nicolas Melay

ฉันชอบแนวทางนี้ FYI สำหรับขยะที่เข้ากันได้การโอเวอร์โหลดตัวสร้างนี้SecureStringถูกนำมาใช้ใน. Net Framework 4.0 ใน PowerShell v2 ฉันลองแล้ว (New-Object -TypeName System.Net.NetworkCredential -ArgumentList "u",$SecureString).Passwordแต่น่าเสียดายที่SecureStringมีการแปลงเป็นStringไฟล์. ดูเหมือนว่าการโทรจะประสบความสำเร็จ แต่Passwordคุณสมบัตินั้นมีค่าตามตัวอักษร "System.Security.SecureString" ระวัง.
John Rees

19

ใน 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 เพื่อไม่ให้เกิดประโยชน์
Tony
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.