Можете ли вы использовать PtrToStringAuto для расшифровки защищенной строки в Powershell 7 в macOS? - PullRequest
2 голосов
/ 26 февраля 2020

Мне не удалось получить следующий фрагмент кода для вывода «Hello World!» в PS7

$("Hello World!" | ConvertTo-SecureString -AsPlainText -Force)
[System.Runtime.InteropServices.Marshal]::PtrToStringAuto(
[System.Runtime.InteropServices.Marshal]::SecureStringToBSTR($string))

Приведенный выше код является примером расшифровки защищенной строки без указания длины.

Этот же код работает в PS6 и PS5 для полной расшифровки защищенной строки, но делает не работает в PS7. Единственный способ обойти это - использовать PtrToStringBSTR. Затем он работает, как и ожидалось, во всех версиях PS для этого варианта использования.

Я поднял проблему в репозитории Powershell на Github, но не получил никаких ответов. Я, честно говоря, просто ищу подтверждение того, что поведение у всех одинаковое.

https://github.com/PowerShell/PowerShell/issues/11953

Я бы подумал, что подобное будет серьезным изменением для большого количества кода, портируемого на PS7.

Вот что я нашел до сих пор:

Документация

https://docs.microsoft.com/en-us/dotnet/api/system.runtime.interopservices.marshal.ptrtostringauto?view=netframework-4.8

Согласно документации, при указании целого числа, PtrToStringAuto:

Allocates a managed String and copies the specified number of characters from a string stored in unmanaged memory into it.

Указание целого числа из 11 Возвращает «Hello», это потому, что каждый другой символ возвращается Null. В этом случае вы должны указать значение int, равное 23, чтобы вернуть полную строку «Hello World!» используя этот метод. Я сохранил вывод в переменной, чтобы продемонстрировать это.

$String = $("Hello World!" | ConvertTo-SecureString -AsPlainText -Force)
[System.Runtime.InteropServices.Marshal]::PtrToStringAuto(
[System.Runtime.InteropServices.Marshal]::SecureStringToBSTR($string), 23)

$String[0] Returns H
$String[1] Returns NULL
$String[2] Returns E
$String[3] Returns NULL
etc.... 

Если целое число не указано, PtrToStringAuto:

Allocates a managed String and copies all characters up to the first null character from a string stored in unmanaged memory into it.

Я полагаю, что это предполагает, что либо Secure String хранится со значениями NULL, тогда как в PS6 это не было, или что поведение функции PtrToStringAuto изменилось, и теперь придерживается поведения, описанного в документации выше.

Это только проблема на macOS; однако использование PtrToStringBSTR вместо PtrToStringAuto для дешифрования Secure String работает, как и ожидалось, для windows и macOS.

Это, похоже, связано: { ссылка }

Я также нигде не вижу, чтобы было внесено изменение.

1 Ответ

2 голосов
/ 26 февраля 2020

Обратите внимание, что [securestring] это больше не рекомендуется для нового кода больше .

Пока на Windows безопасные строки предложить ограниченную защиту - путем сохранения строки в зашифрованном виде в памяти - через DPAPI - и путем сокращения окна, в течение которого текстовое представление является в памяти вообще не шифруется используется на Unix -подобных платформах . [1]


Единственный способ обойти это - использовать PtrToStringBSTR.

Это не только способ обойти проблему, PtrToStringBSTR - это метод, который должен был использоваться для начала с , учитывая, что входная строка имеет вид BSTR. [2]

Обратите внимание, что преобразование защищенной строки в обычный экземпляр [string] и обратно исключает саму цель использования [securestring] для начала с : в результате вы получите текстовое представление ваших конфиденциальных данных. a в памяти вашего процесса, время жизни которого вы не можете контролировать.

Если вы действительно хотите это сделать, более простой, кросс-платформенный подход:

[System.Net.NetworkCredential]::new('dummy', $string).Password

[1] Это особенно проблематично c, когда вы сохраняете защищенную строку в файле , через ConvertFrom-SecureString или Export-CliXml - см. этот ответ .

[2] Auto in PtrToStringAuto() означает, что предполагается, что неуправляемая строка ввода использует кодировку , соответствующую платформе , тогда как BSTR - это строка "Unicode" (UTF-16) на всех платформах. В Windows предполагается, что неуправляемая строка имеет кодировку UTF-16 (именно поэтому код работает), тогда как на Unix -подобных платформах это UTF-8 начиная с. NET Core 3.0 (PowerShell) [Core] 7.0 основан на. NET Core 3.1) , что объясняет ваши симптомы: символы NUL. в BSTR экземпляры кода UTF-16 экземпляра интерпретируются как символы сами по себе, когда (неправильно) интерпретируются как UTF-8. Обратите внимание, что . NET Core 2.x (на котором основан PowerShell [Core] 6.x) (неуместно) по умолчанию - UTF-16 , который этот PR исправлен, что составляет критическое изменение.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...