Chuyển đổi một chuỗi an toàn thành văn bản thuần túy


87

Tôi đang làm việc trong PowerShell và tôi có mã chuyển đổi thành công mật khẩu do người dùng nhập thành văn bản thuần túy:

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

Tôi đã thử một số cách để chuyển đổi nó trở lại, nhưng không có cách nào trong số chúng dường như hoạt động bình thường. Gần đây nhất, tôi đã thử những cách sau:

$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

Điều này cũng mang lại cho tôi một lỗi.

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

Có ai biết về một cách sẽ làm việc cho điều này?

Câu trả lời:


115

Bạn đã đóng, nhưng tham số bạn chuyển đến SecureStringToBSTRphải là a SecureString. Có vẻ như bạn đang chuyển kết quả ConvertFrom-SecureStringlà một chuỗi tiêu chuẩn được mã hóa. Vì vậy, hãy gọi ConvertTo-SecureStringđiều này trước khi chuyển đến SecureStringToBSTR.

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

4
Tôi rất vui vì nó hoạt động. Hãy cẩn thận với chuỗi của bạn, bây giờ, nó là một biến chuỗi không an toàn có thể chứa một thứ gì đó quan trọng như mật khẩu - nó không còn an toàn trong bộ nhớ quy trình của bạn, v.v.
MatthewG

19
Theo tài liệu Marshal.SecureStringToBSTR : Bởi vì phương pháp này phân bổ bộ nhớ không được quản lý cần thiết cho một chuỗi, luôn giải phóng BSTR khi hoàn tất bằng cách gọi phương thức ZeroFreeBSTR . Vì vậy, bạn phải thực hiện những điều sau đây cuối cùng: [Runtime.InteropServices.Marshal]::ZeroFreeBSTR($BSTR).
Rosberg Linhares

@RosbergLinhares - Vì chúng tôi (có lẽ là) tập trung vào powershell, có lý do gì khiến bạn không thể làm $BSTR = $nullvậy?
Orangutech

3
@Orangutech Bạn không thể chỉ đặt biến thành $null, vì ở đây chúng ta đang xử lý các đối tượng không được quản lý. Bạn sẽ không gặp lỗi ngay lập tức, nhưng tôi nghĩ rằng bạn có thể gặp vấn đề khi thời gian trôi qua.
Rosberg Linhares

1
Ngoài việc rò rỉ bộ nhớ do cuộc gọi bị thiếu ZeroFreeBSTR(), như đã nêu, việc sử dụng PtrToStringAuto()luôn có sai sót về mặt khái niệm và - hiện tại PowerShell là nền tảng đa nền tảng - không thành công trên các nền tảng giống Unix. Nó phải luôn luôn như vậy PtrToStringBSTR() - hãy xem câu trả lời này .
mklement0

81

Bạn cũng có thể sử dụng PSCredential.GetNetworkCredential ():

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

Tôi đã thử nghiệm cả hai phương pháp và chúng vẫn đúng.
Maximilian Burszley

10
Đã ủng hộ giải pháp này vì nó mạnh mẽ hơn.
Jim

1
Sử dụng System.Management.Automation.PSCredentialtrong các phiên bản PS cũ hơn khi tên loại ngắn không được nhận dạng.
sao hỏa vào

1
Ngắn hơn:[PSCredential]::new(0, $SecurePassword).GetNetworkCredential().Password
majkinetor

Ngắn hơn:[System.Net.NetworkCredential]::new("", $SecurePassword).Password
K. Frank

36

Cách dễ nhất để chuyển đổi lại nó trong PowerShell

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

1
Thật vậy, không cần phải thông qua PSCredential.
Nicolas Melay

Tôi thích cách tiếp cận này. FYI cho những người nghiện tương thích, việc lấy quá tải hàm tạo SecureStringnày đã được giới thiệu trong .Net Framework 4.0. Trên PowerShell v2, tôi đã thử (New-Object -TypeName System.Net.NetworkCredential -ArgumentList "u",$SecureString).Passwordnhưng không may SecureStringlà nó được chuyển đổi thành a String. Cuộc gọi dường như thành công, nhưng thuộc Passwordtính sau đó là giá trị theo nghĩa đen "System.Security.SecureString". Hãy cẩn thận.
John Rees

17

Trong PS 7, bạn có thể sử dụng 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
Điều này làm tôi phát điên. Tôi đã cố gắng sử dụng cú pháp này trong v5 nhưng không có kết quả.
Tony
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.