Не стесняйтесь поправлять меня, если мои предположения здесь неверны, но позвольте мне объяснить, почему я спрашиваю.
Взято из MSDN, а SecureString
:
Представляет текст, который должен быть конфиденциальным. Текст зашифрован для конфиденциальности при использовании и удален из памяти компьютера, когда он больше не нужен.
Я понимаю, что имеет смысл хранить пароль или другую личную информацию в более SecureString
чем System.String
, потому что вы можете контролировать, как и когда она фактически хранится в памяти, потому что System.String
:
является одновременно неизменным и, если больше не нужен, не может быть программно запланирован для сбора мусора; то есть экземпляр только для чтения после его создания, и невозможно предсказать, когда экземпляр будет удален из памяти компьютера. Следовательно, если объект String содержит конфиденциальную информацию, такую как пароль, номер кредитной карты или личные данные, существует риск, что эта информация может быть раскрыта после ее использования, поскольку ваше приложение не может удалить данные из памяти компьютера.
Однако, в случае приложения с графическим интерфейсом (например, ssh-клиента), SecureString
он должен быть построен из System.String
. Все текстовые элементы управления используют строку в качестве основного типа данных .
Таким образом, это означает, что каждый раз, когда пользователь нажимает клавишу, старая строка, которая была там, отбрасывается, и создается новая строка, представляющая значение в текстовом поле, даже если используется маска пароля. И мы не можем контролировать, когда или если какие-либо из этих значений будут удалены из памяти .
Теперь пришло время войти на сервер. Угадай, что? Вам нужно передать строку через соединение для аутентификации . Итак, давайте преобразуем наше SecureString
в System.String
.... и теперь у нас есть строка в куче, и мы не можем заставить ее пройти сборку мусора (или записать 0 в ее буфер).
Моя точка : независимо от того , что вы делаете, где - то вдоль линии, что SecureString
это собирается быть преобразованы в System.String
, то есть это будет по крайней мере , существует на куче в какой - то момент (без каких - либо гарантий сбора мусора).
Моя точка зрения не в том, существуют ли способы обойти отправку строки в ssh-соединение или обойти, если элемент управления хранит строку (создайте пользовательский элемент управления). Для этого вопроса вы можете заменить «ssh connection» на «форму входа в систему», «форму регистрации», «форму оплаты», «форму« еда, которую вы будете кормить щенком, но не ваши дети »», и т.п.
- Итак, в какой момент использование
SecureString
фактически становится практичным? - Стоит ли когда-нибудь дополнительное время разработки, чтобы полностью искоренить использование
System.String
объекта? - Неужели весь смысл в том,
SecureString
чтобы просто сократить время нахожденияSystem.String
в куче (уменьшая риск перехода к физическому файлу подкачки)? - Если у злоумышленника уже есть средства для проверки кучи, то, скорее всего, у него (A) уже есть средства для чтения нажатий клавиш, или (B) уже физически есть машина ... Так что, если бы он воспользовался,
SecureString
чтобы он не смог добраться до данные в любом случае? - Это просто «безопасность через неизвестность»?
Извините, если я задаю слишком толстые вопросы, любопытство только что одолело меня. Не стесняйтесь отвечать на любые или все мои вопросы (или скажите, что мои предположения совершенно неверны). :)
SecureString
это не совсем безопасная строка. Это просто способ уменьшить временное окно, в котором кто-то может проверить вашу память и успешно получить конфиденциальные данные. Это не пуленепробиваемое и не должно было быть. Но пункты, которые вы поднимаете, очень актуальны. Связанный: stackoverflow.com/questions/14449579/…Ответы:
Есть на самом деле очень практическое использование
SecureString
.Вы знаете, сколько раз я видел такие сценарии? (ответ: много!)
RedGate
программное обеспечение, которое может захватывать «значение» локальных переменных в случае исключений, удивительно полезно. Хотя я могу себе представить, что он будет регистрировать «строковые пароли» случайно.Вы знаете, как избежать всех этих проблем?
SecureString
, Как правило, это гарантирует, что вы не делаете глупых ошибок как таковых. Как это избежать? Убедившись в том, что пароль зашифрован в неуправляемой памяти, а реальное значение доступно только тогда, когда вы на 90% уверены в том, что делаете.В смысле
SecureString
работает довольно легко:1) Все зашифровано
2) Пользовательские звонки
AppendChar
3) Расшифруйте все в НЕМЕДЛЕННОЙ ПАМЯТИ и добавьте персонажа
4) Зашифруйте все снова в НЕЗАМЕНИМОЙ ПАМЯТИ.
Что если у пользователя есть доступ к вашему компьютеру? Сможет ли вирус получить доступ ко всем
SecureStrings
? Да. Все, что вам нужно сделать, это подключиться,RtlEncryptMemory
когда расшифровывается память, вы получите местоположение адреса незашифрованной памяти и прочитаете его. Вуаля! Фактически, вы можете создать вирус, который будет постоянно проверять использованиеSecureString
и регистрировать все действия с ним. Я не говорю, что это будет легкая задача, но это можно сделать. Как видите, «мощь»SecureString
полностью исчезает, когда в вашей системе есть пользователь / вирус.У вас есть несколько пунктов в вашем посте. Конечно, если вы используете некоторые элементы управления пользовательского интерфейса, которые содержат «строковый пароль» внутри, использование фактического
SecureString
не очень полезно. Хотя, тем не менее, он может защитить от некоторой глупости, которую я перечислил выше.Также, как уже отмечали другие, WPF поддерживает PasswordBox, который используется
SecureString
внутри через свойство SecurePassword .Суть в том, если у вас есть конфиденциальные данные (пароли, кредитные карты, ...), используйте
SecureString
. Это то, что C # Framework придерживается. Например,NetworkCredential
класс хранит пароль какSecureString
. Если вы посмотрите на это , вы увидите более 80 различных вариантов использования в .NET FrameworkSecureString
.Есть много случаев, когда вам нужно преобразовать
SecureString
в строку, потому что некоторые API ожидают этого.Обычная проблема:
Вы подняли хороший вопрос: что происходит, когда
SecureString
преобразуется вstring
? Это может произойти только из-за первого пункта. Например, API не знает, что это конфиденциальные данные. Я лично не видел, чтобы это произошло. Получить строку из SecureString не так просто.Это не просто по простой причине ; оно никогда не предназначалось для того, чтобы позволить пользователю преобразовать SecureString в строку, как вы заявили: GC сработает. Если вы видите, что делаете это, вам нужно отойти назад и спросить себя: зачем я это делаю, или мне действительно нужно это зачем?
Есть один интересный случай, который я видел. А именно, функция WinApi LogonUser принимает LPTSTR в качестве пароля, что означает необходимость вызова
SecureStringToGlobalAllocUnicode
. Это в основном дает вам незашифрованный пароль, который находится в неуправляемой памяти. Вам нужно избавиться от этого, как только вы закончите:Вы всегда можете расширить
SecureString
класс с помощью метода расширения, напримерToEncryptedString(__SERVER__PUBLIC_KEY)
, который дает вамstring
экземпляр,SecureString
который зашифрован с использованием открытого ключа сервера. Только сервер может затем расшифровать его. Проблема решена: сборщик мусора никогда не увидит «оригинальную» строку, так как вы никогда не выставите ее в управляемой памяти. Это именно то, что делается вPSRemotingCryptoHelper
(EncryptSecureStringCore(SecureString secureString)
).И как что-то очень похожее : Mono SecureString вообще не шифрует . Реализация была закомментирована, потому что .. жду этого .. "Это как-то вызывает разрыв теста nunit" , что подводит к моему последнему замечанию:
SecureString
не поддерживается везде Если платформа / архитектура не поддерживаетSecureString
, вы получите исключение. Там есть список платформ, которые поддерживаются в документации.источник
SecureString
что было бы намного более практичным, если бы существовал механизм доступа к отдельным персонажам. Эффективность такого механизма может быть повышена за счет имеющего тип структурыSecureStringTempBuffer
без каких - либо общественных членов, которые могут быть переданы с помощьюref
кSecureString
«чтения один символ» метод [если шифрование / дешифрование обрабатывается в 8-символьных кусков, такая структура может содержать данные для 8 символов и расположение первого из этих символов в пределахSecureString
].SecureString
его, его необходимо использовать на протяжении всего стека.EngineSettings
в вашем методе расширения?SecureString
ее не следует использовать для новой разработки ?В ваших предположениях мало вопросов.
Прежде всего, класс SecureString не имеет конструктора String. Для его создания вы выделяете объект, а затем добавляете символы.
В случае графического интерфейса пользователя или консоли вы можете очень легко передать каждую нажатую клавишу в защищенную строку.
Класс разработан таким образом, что вы не можете по ошибке получить доступ к сохраненному значению. Это означает, что вы не можете получить в
string
качестве пароля непосредственно от него.Таким образом, для его использования, например, для аутентификации через Интернет, вам придется использовать соответствующие классы, которые также являются безопасными.
В .NET Framework у вас есть несколько классов, которые могут использовать SecureString
(Больше)
В заключение, класс SecureString может быть полезен, но требует большего внимания со стороны разработчика.
Все это, с примерами, хорошо описано в документации MSStnt SecureString.
источник
SecureString
по сети без сериализации вstring
? Я думаю, что точка зрения ОП заключается в том, что наступает момент, когда вы действительно хотите использовать значение, хранящееся в безопасном месте, аSecureString
это означает, что вы должны вывести его оттуда, и это больше не безопасно. Во всей библиотеке классов Framework практически нет методов, которые принимаютSecureString
входные данные напрямую (насколько я вижу), так какой смысл держать значение внутри aSecureString
в первую очередь?char[]
и отправив каждыйchar
из них через сокет, не создавая в процессе никаких объектов для сбора мусора.SecureString полезна, если:
Вы строите его символ за символом (например, из ввода с консоли) или получаете его из неуправляемого API
Вы используете его, передавая его неуправляемому API (SecureStringToBSTR).
Если вы когда-нибудь преобразуете его в управляемую строку, вы победили ее назначение.
ОБНОВЛЕНИЕ в ответ на комментарий
После преобразования в BSTR неуправляемый компонент, который использует BSTR, может обнулить память. Неуправляемая память более безопасна в том смысле, что ее можно сбросить таким образом.
Однако в .NET Framework очень мало API-интерфейсов, поддерживающих SecureString, поэтому вы правы, говоря, что сегодня это очень ограниченная ценность.
Основной вариант использования, который я вижу, - это клиентское приложение, которое требует от пользователя ввода высокочувствительного кода или пароля. Пользовательский ввод может использоваться символ за символом для создания SecureString, затем он может быть передан в неуправляемый API, который обнуляет BSTR, который он получает после его использования. Любой последующий дамп памяти не будет содержать чувствительную строку.
В серверном приложении трудно понять, где это будет полезно.
ОБНОВЛЕНИЕ 2
Одним из примеров .NET API, который принимает SecureString, является этот конструктор для класса X509Certificate . Если вы говорите с ILSpy или аналогичным, вы увидите, что SecureString внутренне преобразуется в неуправляемый буфер (
Marshal.SecureStringToGlobalAllocUnicode
), который затем обнуляется, когда завершается с (Marshal.ZeroFreeGlobalAllocUnicode
).источник
SecureString
входные данные, что бы их использовать? Вы всегда должны будете вернуться обратноstring
рано или поздно (или,BSTR
как вы упоминаете, это не кажется более безопасным). Так зачемSecureString
вообще?Microsoft не рекомендует использовать
SecureString
для более новых кодов.Из документации класса SecureString :
Который рекомендует:
источник
Как вы правильно определили,
SecureString
предлагает одно конкретное преимущество передstring
: детерминированное стирание. Есть две проблемы с этим фактом:SecureString
. Это означает, что вы должны быть осторожны, чтобы никогда не создавать управляемый GC неизменяемыйstring
или какой-либо другой буфер, в котором будет храниться конфиденциальная информация (или вам также придется отслеживать это ). На практике это не всегда легко достичь, потому что многие API предлагают только способ работыstring
, а неSecureString
. И даже если вам удастся все правильно ...SecureString
защищает от очень специфических видов атак (и для некоторых из них это даже не так надежно). Например,SecureString
позволяет ли вам сократить временное окно, в котором злоумышленник может сбросить память вашего процесса и успешно извлечь конфиденциальную информацию (опять же, как вы правильно указали), но надеясь, что окно слишком мало для злоумышленника сделать снимок вашей памяти вообще не считается безопасностью.Итак, когда вы должны его использовать? Только когда вы работаете с чем-то, что может позволить вам работать
SecureString
для всех ваших потребностей, и даже тогда вы должны помнить, что это безопасно только в определенных обстоятельствах.источник
Ниже текст скопирован из статического анализатора кода HP Fortify
Аннотация: Метод PassString () в PassGenerator.cs хранит конфиденциальные данные небезопасным способом (т. Е. В виде строки), что позволяет извлекать данные путем проверки кучи.
Объяснение: Конфиденциальные данные (такие как пароли, номера социального страхования, номера кредитных карт и т. Д.), Хранящиеся в памяти, могут быть утечки, если они хранятся в управляемом объекте String. Строковые объекты не закреплены, поэтому сборщик мусора может переместить эти объекты по своему желанию и оставить несколько копий в памяти. Эти объекты по умолчанию не зашифрованы, поэтому любой, кто сможет прочитать память процесса, сможет увидеть его содержимое. Кроме того, если память процесса будет выгружена на диск, незашифрованное содержимое строки будет записано в файл подкачки. Наконец, поскольку объекты String являются неизменяемыми, удаление значения String из памяти может быть выполнено только сборщиком мусора CLR. Сборщик мусора не требуется для запуска, если CLR не хватает памяти, поэтому нет никакой гарантии, когда будет происходить сборка мусора.
Рекомендации: вместо хранения конфиденциальных данных в таких объектах, как Strings, храните их в объекте SecureString. Каждый объект всегда хранит свое содержимое в зашифрованном формате в памяти.
источник
Я хотел бы обратиться к этому вопросу:
Злоумышленник может не иметь полного доступа к компьютеру и приложению, но может иметь средства для доступа к некоторым частям памяти процесса. Обычно это вызвано ошибками, такими как переполнение буфера, когда специально сконструированный ввод может привести к тому, что приложение откроет или перезапишет некоторую часть памяти.
HeartBleed утечка памяти
Возьмите Heartbleed, например. Специально сконструированные запросы могут привести к тому, что код предоставит злоумышленнику случайные части памяти процесса. Злоумышленник может извлечь SSL-сертификаты из памяти, но единственное, что ему нужно, это просто использовать некорректный запрос.
В мире управляемого кода переполнения буфера становятся проблемой гораздо реже. А в случае WinForms данные уже хранятся небезопасным образом, и вы ничего не можете с этим поделать. Это делает защиту
SecureString
практически бесполезной.Тем не менее, GUI может быть запрограммирован для использования
SecureString
, и в этом случае уменьшение окна доступности пароля в памяти может стоить того. Например, PasswordBox.SecurePassword из WPF имеет типSecureString
.источник
Некоторое время назад мне пришлось создать интерфейс ac # против шлюза оплаты через кредитную карту java, и один из них нуждался в совместимом шифровании ключей защищенной связи. Поскольку реализация Java была довольно специфичной, и мне пришлось работать с защищенными данными определенным образом.
Я обнаружил, что этот дизайн довольно прост в использовании и проще, чем работа с SecureString ... для тех, кто любит использовать ... не стесняйтесь, никаких юридических ограничений :-). Обратите внимание, что эти классы являются внутренними, вам может потребоваться сделать их общедоступными.
источник