Защитная лазейка вокруг изменений пароля с помощью .NET FormsAuthentication и постоянных файлов cookie?
ОК, здесь сценарий:
- Боб записывается в mysite.com, который использует аутентификацию .NET-форм, и тикает "помни меня".
- Ева крадет ноутбук Боба
- Боб получает новый ноутбук и меняет свой пароль.
Теперь на данный момент у Eve есть украденный ноутбук, на котором хранится постоянный файл cookie, который будет записывать ее на mysite.com, как Bob, - и, насколько я могу судить, это будет работать даже после того, как Bob изменил свой пароль.
По умолчанию cookie проверки подлинности форм не содержит пароля Боба (будь то открытый, хэшированный или иным образом зашифрованный), поэтому пароль Боба вообще не задействован в процессе аутентификации cookie и то же имя пользователя, которое работало на прошлой неделе будет по-прежнему работать сегодня.
Это достаточно простая лазейка для работы - просто установив FormsAuthentication.SetAuthCookie( "username: passwordHash" ) или что-то, а затем расшифровывая и разбивая куки файлы в вашем обработчике проверки подлинности, но я не могу поверить, что эта проблема существует "из ящик?... я что-то упустил?
РЕДАКТИРОВАТЬ. Обратите внимание, что я предполагаю, что цель кнопки "запомнить меня" - это запретить вам вводить пароль каждый раз, когда вы посещаете веб-сайт. Это работает на Facebook, Twitter, Gmail и практически на каждом другом сайте, о котором я могу думать, - и я был бы очень удивлен, если это не цель опции "Постоянный куки" в .NET FormsAuthentication.
Кроме того, да, я согласен с тем, что выполнение двухфакторной аутентификации при каждом входящем запросе несет определенные накладные расходы, но в реальном выражении это лишь незначительно дороже, чем извлечение пользователя из базы данных на основе их имени пользователя, которое вы, вероятно, все равно.
РЕДАКТИРОВАТЬ 2. Похоже, что по крайней мере один основной сайт .NET - CodePlex.com - уязвим для этого; см. http://codeplex.codeplex.com/discussions/350646
Ответы
Ответ 1
Возможно, было бы разумно принимать только билеты FormsAuth, выпущенные после вашего последнего пароля reset.
Итак, в Global.asax AuthenticateRequest извлеките FormsAuthenticationTicket.IssueDate из зашифрованного билета и сравните его с датой последнего пароля пользователя reset (вам нужно сохранить это в своей базе данных, когда они reset их пароль).
Если билет был выпущен до этой даты, то отклоните билет, не удостоверяйте его подлинность и попросите снова войти в систему.
Я не реализовал это сам, поэтому я мог бы пропустить дыру в теории где-то...
Ответ 2
Наличие хэшированного пароля в файле cookie для проверки подлинности означает, что вы должны проверять его при каждом запросе. Это было бы неэффективно, поскольку аутентификация может быть дорогостоящей.
Вы можете обеспечить легкое "исправление" для своей озабоченности, связанное с идентификатором в разделе данных пользователя cookie форм. Обратите внимание: если вы создадите файл cookie самостоятельно, вы можете ввести туда произвольные данные, например идентификатор записи пароля.
Теперь вы можете добавить обработчик AuthenticateRequest
в global.asax
. Вы пытаетесь извлечь пользовательские данные из файла cookie, и вы сравниваете извлеченный идентификатор из файла cookie с файлом в базе данных. Если они не совпадают, вы возвращаете ошибку и/или выходите из системы из приложения.