Усиление защиты Web

Недавно мы писали, о применении идентификации устройств, для отсеивания атак перебором, но есть и другие варианты решения проблемы.

Объект: веб-форма входа в систему.
Дана задача: усилить защиту аккаунта пользователя от подбора простого пароля к его аккаунту, используя минимум средств.

Что такое минимум средств? Это не использовать таблицы-справочники для блокировки по IP-адресу и User-Agent. Не использовать лишние запросы к системе, не захламлять систему авторизации лишними циклами.

И, выполнить совершенно волшебное требование — даже если бот введет нужные логин и пароль… не дать ему войти, а вот реального пользователя впустить.

Можно ли так сделать? В теории, конечно, нет. Но в практике, в частном порядке и при определенных условиях, как оказалось, весьма возможно.
Приглашаю под кат за подробностями.

Итак, предположим, что, логин у нашего пользователя «test», а пароль «12345». Мерзкий бот подключил свой словарь сгенерированных паролей, и готов работать со скоростью 700 паролей в секунду. Он знает, что логин пользователя — «test». Ситуация аховая: пароль «12345» будет вычислен за очень малое время. Пользователь, тем временем, открыл сайт и начал вводить логин и пароль в веб-форму логина.

Давайте внесем изменения в систему авторизации, пока ни один из них не начал свою работу, и не случилась беда.

Магия будет заключаться в третьей переменной, которую следует «приклеить» к паре логин-пароль. Я назвал ее touch.

Каждый раз, когда кто-то получает (внимание: получает, а не запрашивает!) логин-пароль, дата «touch» для пользователя «test» обновляется на текущую дату-время:

login/password/touch: 'test', '12345', '2014-12-13 14:00:00'.

Предположим, что бот начал первую итерацию и предложил пароль «1» для логина «test» в ‘2014-12-13 15:00:00’. Cрабатывает контроллер login_check, который читает из базы данных пару логин-пароль, которую никто не «трогал» целых 2 секунды! Откуда вообще эти 2 секунды?! Об этом будет дальше.

Такая пара логин-пароль находится. Разница между последним «touch» и текущим временем — 1 час. Поэтому запись успешно возвращается на наш запрос.

Сначала пара логин-пароль сличается и login_check приходит к выводу, что «test/12345» не равно «test/1». Контроллер возвращает «auth error». А затем дата «touch» для пользователя «test» обновляется на текущую: ‘2014-12-13 15:00:00’.

Бот приступает к следующей итерации: пробует пароль «2». 

Скорость работы бота измеряется микросекундами. Он пытается авторизоваться сразу же: в ‘2014-12-13 15:00:00’. 
И тут вступает в действие наш алгоритм — условие по параметру «touch» уже не выполняется. 2 секунды еще не прошли. Fail.

Модифицированный нашей логикой контроллер «login_check» не может получить пару логин-пароль. 
Запись существует, но ее дата «touch» еще слишком «свежая». 

И она она уже не попадает в выборку. А раз такой пары логин-пароль нет, то контроллер ответит боту «auth error».

Бот не сдается, продолжает подбор и, наконец, приходит к правильному паролю «12345». 
Вероятность, что именно текущая попытка вернет успех — крайне и крайне мала. 1/700 на каждую попытку входа! То есть, если раньше было 1:1, то теперь 1:700. И чем быстрее бот, тем больше вероятность, что его ждет fail.

В итоге только очень малая часть паролей будет действительно проверена. Остальные получат ложные срабатывания, даже если они будут верны.

А что пользователь?
Начнем с пользователя. Пользователь, в отличие от бота, вводит данные в веб-форму руками через клавиатуру и смотрит зрительными органами на монитор. А гибкость его алгоритмических способностей куда лучше, чем бота. По сути, пользователь в некотором роде искусственный интеллект. А значит, часть логики уже лежит в нем. И мы ею воспользуемся!

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

Да, я обещал рассказать про две секунды. Рассказываю:
Две секунды это оптимальное время, за которое пользователь проводит операции по корректировке данных и совершает следующую попытку входа. В эти две секунды пользователь укладывается полностью. Если пользователь не уложился — он всегда может повторить попытку и за это время действие touch уже наверняка аннулируется.

В заключение.
На самом деле алгоритм не совершенен и может создать проблемы пользователю(например когда бот перебирает пароли, и пользователь также пытается зайти, пользователь будет получать autotentification error). Но вполне имеет право на существование.

Share with:


Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *