Дружелюбная защита WEB ресурса от атак перебором

в 20:57, , рубрики: Brute-force attack, Алгоритмы, безопасность, браузеры, информационная безопасность

Одна из проблем, которая возникает перед WEB-ресурсами имеющими персональные кабинеты — атака перебором. Да, простой перебор всех вариантов пароля для конкретной учетки. Тупо? Возможно, но такая атака может сильно нагрузить ресурс. К тому же, если контроля сложности пароля пользователя при регистрации нет, она может оказаться еще и успешной.

Чаще всего, вопрос решается относительно просто. Если пользователь ввел несколько раз неправильно пароль, его учетка блокируется на какое-то время. Альтернативное решение — выводить капчу. Сразу, или после нескольких неудачных попыток. Ну, и не забудем про 2F авторизацию, которая почти неуязвима. Казалось бы — профит! Но, не все так радужно…

Давайте рассмотрим некоторые проблемы описанных решений:

Временная блокировка — учетка пользователя временно заблокирована и он не может попасть в систему. Реальный пользователь в период атаки испытывает душевную боль и терзания. Он не может попасть в систему. И скорее всего нагружает ваш саппорт. А самое интересное, что, возможно, в этом и есть цель атакующего.

Капча — относительно неплохое и эффективное решение. Правда доставляет неудобство пользователю, требуя вводить что-то там дополнительно. Достаточно “неприятно” встраивать в дизайн. Ах да… еще эта штука, в зависимости от реализации, может быть подвержена DoS атаке.

2F авторизация — Все замечательно. Правда… чаще всего это штука опциональная. Включить ее для противодействия атаки не выйдет. Она или есть, или ее нет. А на некоторых ресурсах вводить 2F авторизацию, скажем так, по воробьям из танка стрелять.

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

Если вы пользуетесь почтой, например mail.ru, и у вас установлена 2F авторизация, то возможно уже замечали, что 2F авторизация запрашиваться только для нового “устройства” при первом входе. Далее, устройство считается доверенным. И нужно просто вводить логин и пароль.

Удобная штука. Юзерфрендли, так сказать. Реализуется это двумя токенами. Первый идентификатор “устройства” (определим как devid), а второй сессионный (определим как session). Devid, в отличии от session не теряет актуальности даже после завершения сессии пользователем. Он передается при следующей попытке входа, и если логин/пароль верный, а также devid доверенный, 2F уже не запрашивается. Но, если очередная попытка входа оказалась неудачной, токен devid тут же протухает. И теперь нужно пройти полный путь авторизации.

За основу была взята эта парадигма. Т.е. ввести токен devid, который будет выдаваться постоянно, при любом ответе WEB-ресурса, конечно, если его не было в запросе.

Для случая 2F авторизации был, фактически, реализован вышеописанный алгоритм. И сразу все стали довольны. Т.ч. его детально рассматривать смысла нет. А вот «навороты», лучше рассмотреть на схеме, с пояснениями:

Дружелюбная защита WEB ресурса от атак перебором - 1

Даже, если не установлена 2F авторизация, но вход был успешным, то токен devid помечается как доверенный. Казалось бы, смысла особого нет делать это без 2F авторизации. Но, все чуть хитрее. Если мы знаем, что devid доверенный, т.е. с него был успешный вход, мы как минимум предполагаем, что именно с этого устройства входил реальный юзер. Это очень важная информация, которую использует описываемый алгоритм в своей работе в режиме отражения атаки.

Была принята стратегия: любая авторизация может происходить только при наличии валидного токена devid. Валидный devid отличается от доверенного тем, что он еще НЕ доверенный, т.е. с него не было успешных входов, но система готова обрабатывать с ним запросы на авторизацию. На один валидный токен количество попыток ограничено N раз. Если происходит ошибка авторизации более N раз подряд, токен помечается как “скомпрометированным”. Он переносится в отдельный журнал со статистикой подбора. Запросы с его участием продолжают обрабатываться, но… залогиниться с ним уже нельзя. Все, что происходит — накопление статистики активности.

Так отбиваются самые глупые атаки. Например, если атакующий, игнорируя devid, пытается логиниться в систему или если он не смог понять логику работы devid (откуда ему знать сколько дается попыток логина с одним и тем же devid?), его запросы терминируются.

Собственный фронт знает, что после N раз неуспешных попыток входа с одного devid, он уже “протух”. Теперь нужно получить новый токен, перед очередной попыткой логина.

Казалось бы, что за глупость? Фронтом отрабатывать попытки входа… но, как я уже сказал выше, все хитрее. Если пользователь работает через штатный фронт вероятность того, что он действительно пытается атаковать систему ничтожна мала. В паре с системой контроля сложности пароля при регистрации пользователя это совершенно бесперспективно. Скорее всего, реальный пользователь, реально пытается вспомнить свой пароль.

Ну так в чем же хитрость? В том, что на бэке мы генерируем те самые валидные devid с определенным лимитом по времени. Например, не более 1000 шт в минуту. Если вдруг этот лимит превышен, врубается режим атаки. И тут либо можно пойти радикально и прекратить эмиссию devid на какое-то время, что резко охладит пыл атакующего, либо уменьшить объем генерации валидных devid. А можно, включить ту самую капчу, для всех валидных, но недоверенных devid.

Таким образом получается гибкая система контроля и управления атаками. Образуются надежные метрики по которым может срабатывать мониторинг поднимая тревогу. Накопленную статистику можно преобразовывать в правила блокировки и т.п.

А дружелюбной система является потому, что те пользователи, которые ранее входили в нее, т.е. имеют доверенные devid даже не заметят атаки. Они будут пропускаться системой без проблем.

Вот теперь профит. Данный алгоритм весьма неплохо зарекомендовал себя на ресурсах с весьма высокой нагрузкой. Были, в том числе, попытки DoS на сам алгоритм, но и тут он показал себя достойно.

Автор: Роман

Источник

* - обязательные к заполнению поля


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js