Я пытаюсь обмануть цель SecureString .NET. Из MSDN:
Экземпляр класса System.String является неизменным и, если он больше не нужен, не может быть программно запланирован для сборки мусора; то есть экземпляр только для чтения после его создания, и невозможно предсказать, когда экземпляр будет удален из памяти компьютера. Следовательно, если объект String содержит конфиденциальную информацию, такую как пароль, номер кредитной карты или личные данные, существует риск, что эта информация может быть раскрыта после ее использования, поскольку ваше приложение не может удалить данные из памяти компьютера.
Объект SecureString похож на объект String в том смысле, что он имеет текстовое значение. Однако значение объекта SecureString автоматически шифруется, может изменяться до тех пор, пока приложение не помечает его как доступное только для чтения, и может быть удалено из памяти компьютера вашим приложением или сборщиком мусора .NET Framework.
Значение экземпляра SecureString автоматически шифруется при инициализации экземпляра или при изменении значения. Ваше приложение может сделать экземпляр неизменным и предотвратить его дальнейшее изменение, вызвав метод MakeReadOnly.
Является ли автоматическое шифрование большой отдачей?
И почему я не могу просто сказать:
SecureString password = new SecureString("password");
вместо того
SecureString pass = new SecureString();
foreach (char c in "password".ToCharArray())
pass.AppendChar(c);
Какой аспект SecureString мне не хватает?
источник
SecureString
для новой разработки: github.com/dotnet/platform-compat/blob/master/docs/DE0001.mdОтветы:
Я бы прекратил использовать SecureString. Похоже, парни из PG отказались от поддержки. Возможно, даже потяните его в будущем - https://github.com/dotnet/apireviews/tree/master/2015-07-14-securestring .
источник
Некоторые части фреймворка, которые в настоящее время используют
SecureString
:System.Windows.Controls.PasswordBox
управления WPF хранит пароль внутри SecureString (предоставляется как копия черезPasswordBox::SecurePassword
)System.Diagnostics.ProcessStartInfo::Password
СвойствоSecureString
X509Certificate2
принимаетSecureString
для пароляОсновная цель - уменьшить поверхность атаки, а не устранить ее.
SecureStrings
«закреплены» в ОЗУ, поэтому сборщик мусора не будет перемещать его или копировать. Это также гарантирует, что простой текст не будет записан в файл подкачки или в дампы ядра. Шифрование больше похоже на запутывание и не остановит решительного хакера, который сможет найти симметричный ключ, используемый для его шифрования и дешифрования.Как уже говорили другие, причина, по которой вы должны создать
SecureString
посимвольный символ, заключается в первом очевидном недостатке, заключающемся в том, чтобы поступить иначе: вы, вероятно, уже имеете секретное значение в виде простой строки, так какой в этом смысл?SecureString
Это первый шаг в решении проблемы с курицей и яйцом, поэтому, несмотря на то, что большинство современных сценариев требуют преобразования их обратно в обычные строки, чтобы вообще их использовать, их существование в среде теперь означает лучшую поддержку для них в будущее - по крайней мере, до такой степени, что ваша программа не должна быть слабым звеном.источник
Изменить : не использовать SecureString
Текущее руководство теперь говорит, что класс не должен использоваться. Подробности можно найти по этой ссылке: https://github.com/dotnet/platform-compat/blob/master/docs/DE0001.md
Из статьи:
DE0001: SecureString не должен использоваться
мотивация
SecureString
состоит в том, чтобы избежать сохранения секретов в памяти процесса в виде простого текста.SecureString
как концепция ОС не существует.System.String
- время жизни собственного буфера короче.Рекомендация
Не используйте
SecureString
для нового кода. При переносе кода на .NET Core учтите, что содержимое массива не зашифровано в памяти.Общий подход к работе с учетными данными - избегать их и вместо этого полагаться на другие средства аутентификации, такие как сертификаты или проверка подлинности Windows.
Конец редактирования: Исходное резюме ниже
Много хороших ответов; Вот краткий обзор того, что обсуждалось.
Microsoft внедрила класс SecureString, стремясь обеспечить более надежную защиту конфиденциальной информацией (например, кредитными картами, паролями и т. Д.). Это автоматически обеспечивает:
В настоящее время SecureString ограничен в использовании, но в будущем ожидают лучшего внедрения.
Основываясь на этой информации, конструктор SecureString не должен просто брать строку и разрезать ее до массива char, поскольку указанная строка отрицательно сказывается на цели SecureString.
Дополнительная информация:
Изменить: мне было трудно выбрать лучший ответ, так как во многих есть хорошая информация; Жаль, что нет вариантов ответа с помощью.
источник
Короткий ответ
Потому что теперь у вас
password
в памяти; без возможности стереть его - в этом и заключается смысл SecureString .Длинный ответ
Причина, по которой SecureString существует, заключается в том, что вы не можете использовать ZeroMemory для очистки конфиденциальных данных, когда закончите с ними. Он существует для решения проблемы, которая существует из- за CLR.
В обычном родном приложении вы бы назвали
SecureZeroMemory
:Примечание : SecureZeroMemory идентичен
ZeroMemory
, за исключением того, что компилятор не оптимизирует его.Проблема в том, что вы не можете позвонить
ZeroMemory
илиSecureZeroMemory
внутри .NET. И в .NET строки неизменны; вы даже не можете перезаписать содержимое строки, как на других языках:Так что ты можешь сделать? Как мы можем предоставить в .NET возможность стереть пароль или номер кредитной карты из памяти, когда мы закончили с этим?
Единственный способ сделать это можно было бы поместить строку в какой - то родной блок памяти, где вы можете затем позвонить
ZeroMemory
. Нативный объект памяти, такой как:SecureString возвращает утраченную способность
В .NET строки не могут быть стерты, когда вы закончите с ними:
Dispose
из нихSecureString существует как способ обойти безопасность строк и иметь возможность гарантировать их очистку, когда это необходимо.
Вы задали вопрос:
Потому что теперь у вас
password
в памяти; без возможности вытереть его. Он застрял там, пока CLR не решит повторно использовать эту память. Вы вернули нас туда, где мы начали; работающее приложение с паролем, от которого мы не можем избавиться, и где дамп памяти (или Process Monitor) может видеть пароль.SecureString использует API защиты данных для хранения строки, зашифрованной в памяти; таким образом, строка не будет существовать в файлах подкачки, аварийных дампах или даже в окне локальных переменных, когда коллега просматривает ваш запрос.
Как мне прочитать пароль?
Тогда возникает вопрос: как мне взаимодействовать со строкой? Вы абсолютно не хотите такой метод, как:
потому что теперь вы вернулись туда, откуда начали - пароль, от которого вы не можете избавиться. Вы хотите заставить разработчиков правильно обрабатывать чувствительную строку, чтобы ее можно было стереть из памяти.
Вот почему .NET предоставляет три удобные вспомогательные функции для маршалинга SecureString в неуправляемую память:
Вы преобразуете строку в неуправляемый блоб памяти, обрабатываете ее, а затем снова стираете.
Некоторые API принимают SecureStrings . Например, в ADO.net 4.5 SqlConnection.Credential принимает набор SqlCredential :
Вы также можете изменить пароль в строке подключения:
И внутри .NET есть много мест, где они продолжают принимать простую строку в целях совместимости, а затем быстро превращают ее в SecureString.
Как поместить текст в SecureString?
Это все еще оставляет проблему:
Это сложная задача, но главное - заставить вас задуматься о безопасности.
Иногда функциональность уже предоставляется для вас. Например, элемент управления WPF PasswordBox может вернуть вам введенный пароль в виде SecureString напрямую:
Это полезно, потому что везде, где вы раньше передавали необработанную строку, теперь у вас есть система типов, жалующаяся на то, что SecureString несовместима со String. Вы хотите идти как можно дольше, прежде чем конвертировать SecureString обратно в обычную строку.
Преобразование SecureString достаточно просто:
как в:
Они просто не хотят, чтобы ты это делал.
Но как мне получить строку в SecureString? Ну, что вам нужно сделать, это перестать иметь пароль в строке в первую очередь. Вы должны были иметь это в чем - то другом. Даже
Char[]
массив будет полезен.Вот когда вы можете добавить каждый символ и стереть открытый текст, когда вы закончите:
Вам нужен пароль , сохраненный в некоторой памяти , которые вы можете протирать. Загрузите его в SecureString оттуда.
tl; dr: SecureString существует для предоставления эквивалента ZeroMemory .
Некоторые люди не видят смысла стирать пароль пользователя из памяти, когда устройство заблокировано , или стирать нажатия клавиш из памяти после их аутентификации . Эти люди не используют SecureString.
источник
Существует очень немного сценариев, в которых вы можете разумно использовать SecureString в текущей версии Framework. Это действительно полезно только для взаимодействия с неуправляемыми API - вы можете упорядочить его с помощью Marshal.SecureStringToGlobalAllocUnicode.
Как только вы конвертируете его в / из System.String, вы побеждаете его назначение.
Пример MSDN генерирует символ SecureString за раз из ввода с консоли и передает защищенную строку в неуправляемый API. Это довольно запутанно и нереально.
Вы можете ожидать, что в будущих версиях .NET будет больше поддержки SecureString, что сделает его более полезным, например:
SecureString Console.ReadLineSecure () или аналогичный для чтения входных данных консоли в SecureString без всего сложного кода в образце.
Замена WinForms TextBox, которая сохраняет свое свойство TextBox.Text в виде защищенной строки, чтобы пароли можно было вводить безопасно.
Расширения API, связанных с безопасностью, позволяющие передавать пароли как SecureString.
Без вышеизложенного SecureString будет иметь ограниченную ценность.
источник
Я полагаю, что причина, по которой вы должны выполнять добавление символов вместо одного простого экземпляра, заключается в том, что в фоновом режиме передача «пароля» в конструктор SecureString помещает эту строку «пароля» в память, разрушая назначение безопасной строки.
Добавляя, вы помещаете в память только персонажа, который не должен быть физически близким друг к другу, что значительно затрудняет восстановление исходной строки. Я могу ошибаться здесь, но так мне это объяснили.
Цель этого класса - предотвратить доступ к защищенным данным с помощью дампа памяти или аналогичного инструмента.
источник
MS обнаружила, что в некоторых случаях сбоя сервера (настольного компьютера и т. Д.) Бывали ситуации, когда среда выполнения делала дамп памяти, раскрывая содержимое содержимого памяти. Secure String шифрует ее в памяти, чтобы злоумышленник не смог получить содержимое строки.
источник
Одним из больших преимуществ SecureString является то, что предполагается исключить возможность сохранения ваших данных на диск из-за кэширования страниц. Если у вас есть пароль в памяти, а затем загружается большая программа или набор данных, ваш пароль может быть записан в файл подкачки, поскольку ваша программа выгружается из памяти. С SecureString, по крайней мере, данные не будут бесконечно бездействовать на вашем диске в виде открытого текста.
источник
Я предполагаю, что это потому, что строка предназначена для безопасности, то есть хакер не должен быть в состоянии прочитать ее. Если вы инициализируете его строкой, хакер может прочитать исходную строку.
источник
Ну, как говорится в описании, значение хранится в зашифрованном виде, что означает, что дамп памяти вашего процесса не будет раскрывать значение строки (без некоторой довольно серьезной работы).
Причина, по которой вы не можете просто создать SecureString из константной строки, заключается в том, что тогда у вас будет незашифрованная версия строки в памяти. Ограничение создания строки по частям снижает риск одновременного хранения всей строки в памяти.
источник
Другой вариант использования - это когда вы работаете с платежными приложениями (POS), и вы просто не можете использовать неизменяемые структуры данных для хранения конфиденциальных данных, потому что вы осторожный разработчик. Например: если я буду хранить конфиденциальные данные карты или метаданные авторизации в неизменяемой строке, всегда будет случай, когда эти данные будут доступны в памяти в течение значительного периода времени после их удаления. Я не могу просто перезаписать это. Еще одно огромное преимущество, когда такие конфиденциальные данные хранятся в памяти в зашифрованном виде.
источник