Реализация безопасных, уникальных «одноразовых» URL-адресов активации в ASP.NET (C #) - PullRequest
23 голосов
/ 02 июня 2009

У меня есть сценарий, при котором пользователям сайта, который я создаю, нужна возможность вводить некоторую основную информацию в веб-форму без необходимости входа в систему. Сайт разрабатывается с использованием ASP.NET/C# и использует MSSQL 2005 для своих реляционных данных.

Пользователям будет отправлено электронное письмо с сайта, содержащее уникальную ссылку для ввода необходимой информации. Электронная почта будет очень похожа на электронную почту, которую мы все получаем при регистрации на таких сайтах, как форумы, и содержит случайно сгенерированный, уникальный параметр URL-адреса, специально относящийся к одной цели (такой как проверка адреса электронной почты для форума).

Мои вопросы касаются безопасного решения этой проблемы. Я рассматривал возможность использования GUID в качестве уникального идентификатора, но не уверен в его влиянии на мир безопасности.

  1. Достаточно ли длинен GUID, чтобы значения не могли быть легко угаданы (или перебраны со временем)?
  2. Является ли реализация .NET GUID достаточно случайной в том смысле, что существует равная вероятность генерации всех возможных значений в «пространстве ключей»?

  3. Если использование GUID является приемлемым подходом, должен ли сайт затем перенаправить информацию с помощью перезаписи URL-адреса или связать информацию в виде данных с GUID в качестве ссылки?

  4. Будет ли использование перезаписи URL скрывать истинный источник данных?

  5. Стоит ли использовать TSQL SELECT NEWID () в качестве генератора GUID для реализации .NET?

  6. Я совершенно не прав с моим подходом к этой проблеме?

Большое спасибо,

Карл

Ответы [ 6 ]

14 голосов
/ 02 июня 2009
  1. Нет, GUID не являются полностью случайными, и большинство битов являются либо статическими, либо легко угадываемыми.
  2. Нет, они не случайные, см. 1. На самом деле очень мало битов, которые на самом деле являются случайными, и при этом не криптографически сильными случайными.
  3. Это не так, см. 1 и 2.
  4. вы можете, но не нужно ... посмотреть мое решение в конце.
  5. Нет, см. 1 и 2
  6. Да.

То, что вы должны использовать вместо GUID, это криптографически сильный генератор случайных чисел - используйте System.Security.Cryptography.RNGCryptoServiceProvider , чтобы генерировать длинную (скажем, 32 байта) строку данных, затем base64 кодировать , что.
Кроме того, если предположить, что это какая-то регистрация с конфиденциальными данными, вам нужно ограничить срок действия ссылки, например, 60 минут или 24 часа - в зависимости от вашего сайта.
Вам нужно будет сопоставить эти значения с конкретными пользователями. Тогда вы можете автоматически представить ему правильную форму по мере необходимости. Не нужно переписывать URL, просто используйте его как идентификатор пользователя (на этой странице).
Конечно, не забудьте, что этот URL должен быть HTTPS ...

Кстати, просто примечание - рекомендуется помещать в электронное письмо какой-либо текст, поясняющий, что пользователи не должны нажимать на ссылки в анонимных письмах, и, как правило, ваш сайт не отправляет, и они никогда не должны вводить свой пароль после нажатия blablabla. ....

О, почти забыл - еще одна проблема, которую вы должны рассмотреть, это то, что происходит, если пользователь хочет отправить ему несколько электронных писем, например, Хиты регистрируются несколько раз. Может ли он делать это снова и снова и получать много действительных URL? Действителен только последний? Или, может быть, одно и то же значение возвращается снова и снова? Конечно, если анонимный пользователь может отправить запрос на это электронное письмо, то может возникнуть проблема с DoS ... не говоря уже о том, что, если он введет свой собственный адрес электронной почты, он может также ввести любой произвольный адрес, наводнив плохую чмо Входящие и, возможно, в результате чего ваш почтовый сервер попал в черный список ...
Ни одного правильного ответа, но необходимо учитывать в контексте вашей заявки.

11 голосов
/ 02 июня 2009
  1. Да, 2 128 достаточно долго.
  2. Нет, реализации GUID предназначены для генерации уникальных GUID, а не случайных. Вы должны использовать криптографически безопасный генератор случайных чисел (например, RNGCryptoServiceProvider) для генерации 16 случайных байтов и инициализации структуры Guid с этим.
  3. Да, это в целом приемлемый подход. Оба будут работать.
  4. Да, если вы не дадите никаких других подсказок
  5. Нет, goto 2
  6. Нет, все нормально. Вам просто нужно использовать криптографически безопасный генератор случайных чисел для генерации GUID.
4 голосов
/ 02 июня 2009

Это может быть излишним, но вы можете хэшировать их адрес электронной почты с помощью SHA1 , используя ваш guid (NewGuid в порядке) в качестве хеш-соли и поместить его в URL. Затем, когда они придут на вашу страницу, вы можете спросить их адрес электронной почты, получить гид и повторно вычислить хеш для проверки. Даже если бы кто-то узнал, какие адреса электронной почты следует использовать, он никогда не сможет сгенерировать коллизию хеш-кода, не зная, с каким гидом вы посолили (или это заняло бы у него немало времени :). Конечно, вам придется сохранить их электронную почту и хеш-соль в базе данных.

4 голосов
/ 02 июня 2009

Я бы рекомендовал использовать просто случайное число, например байты из RNGCryptoServiceProvider.GetBytes . Идентификаторы GUID не должны быть полностью случайными. Они имеют фиксированные биты, и некоторые версии используют ваш MAC-адрес. GetBytes также дает вам возможность использовать более 128 бит (хотя этого должно быть достаточно).

Я думаю, что лучше не помещать данные пользователя в URL. Хотя HTTPS может защитить его при передаче, он все еще может быть в истории браузера пользователя или тому подобное. Лучше использовать POST и связать случайное число со строкой вашей базы данных.

1 голос
/ 02 июня 2009

Во-первых, если возможно, следует ограничить перебор, ограничив пропускную способность запроса (например, ограниченные попытки на IP в секунду и ограниченные общие попытки в секунду).

В зависимости от алгоритма генерации GUID, это может быть не очень хорошая идея. Хотя недавние реализации должны быть «достаточно хорошими», их значения могут быть предсказуемыми. Недавние реализации, такие как в .NET, применяют хэш, в противном случае у вас есть четко идентифицируемые поля для MAC-адреса и времени после загрузки. Однако возможные значения ограничены, поэтому у вас нет истинных 128 случайных битов.

Если безопасность является главным приоритетом, я бы выбрал криптографически сильный генератор случайных чисел и собрал бы строку случайных символов. Это также делает oyu независимым от легко угадываемого алгоритма (как guid. ToString () легко идентифицируется как таковой), для которого атака может быть обнаружена в ближайшем будущем.

Если эти критерии соблюдены, я не вижу проблем с наличием ключа в строке запроса.

0 голосов
/ 05 марта 2015

создайте таблицу в базе данных с linkID и столбцом Datesent, при генерации ссылки отправьте вставьте DateTime.Now в таблицу и верните linkId, установите linkID в качестве параметра строки запроса на ActivationLink. При загрузке страницы активации снова получите linkId и используйте его для вызова хранимой процедуры, которая будет возвращать дату, когда в качестве параметра передается соответствующий linkId. Когда вы возвращаете дату, вы можете добавить, как долго вы хотите, чтобы ссылка оставалась активной используя .AddDays () /. AddMonths это методы C # для datetime. затем сравните дату, которую вы вернули с сегодняшней датой. если прошло больше дней или месяцев, выведите сообщение об ошибке или продолжите и отобразите содержимое страницы. Я рекомендую вам сохранить содержимое страницы на панели и установить его видимым = "ложь", а затем сделать панель видимой = "истина", только если дата все еще находится в пределах диапазона.

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