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

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

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

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

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

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

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

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

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

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

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

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



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

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

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

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

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

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

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

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

    Вот теперь профит. Данный алгоритм весьма неплохо зарекомендовал себя на ресурсах с весьма высокой нагрузкой. Были, в том числе, попытки DoS на сам алгоритм, но и тут он показал себя достойно.
    Поделиться публикацией
    Комментарии 22
      0
      В том, что на бэке мы генерируем те самые валидные devid с определенным лимитом по времени. Например, не более 1000 шт в минуту.

      А храните их где? Я бы снял нагрузку на их прегенерацию и хранение добавлением поля devid_sign (шифрование), по которому и проверять валидность. А счётчик неуспешных попыток положил бы в redis, с устареванием по времени.
        0
        Да. Вы правы. Некоторые моменты я оставил за «скобками». Реализация не так важна как идея. Ну к примеру, очередной devid генерируется с учетом ip запроса. В хеше включен. И с другого он уже не валиден, если не достоверный. И срок жизни имеет. Иначе атакующий может накопить их а затем атаковать. Это уже тонкости зависящие от потребностей.
        –1

        Когда же в России будут защищать свои Web-ресурсы российскими шифрсьютами!

          +1
          Временная блокировка — учетка пользователя временно заблокирована и он не может попасть в систему. Реальный пользователь в период атаки испытывает душевную боль и терзания.
          Что за дурацкий выбор блокируемого. Почему нельзя заблокировать айпишник атакующего вместо учётки атакуемого?
            +4
            Потому что nat?
              0

              Да. Верно. Nat. Но и еще потому, что нужно понять какой ip блокировать. Статистика нужна. Часто такие атики идут через проксики. Про ботнеты я молчу. Так можно пол сети перестрелять… а толку недобиться.

                0
                1. Вы блокируете страницу авторизации целой подсети, которая за натом.
                2. Пользователи этой подсети ругаются с провайдером.
                3. Провайдер находит атакующего и даёт ему по шапке.
                4. Все в выигрыше.
                  +1

                  Эм… :)) как я в этих случаях говорю — я рад, что у нас есть такие ответственные граждане. Но очень жаль, что я их живыми не видел…

                    +1
                    2. Пользователи этой подсети ругаются с провайдером уходят и больше не возвращаются, потому как — там логин сломан.
                0
                +
                  0
                  Спасибо!
                  0
                  В статье не сказано преимущества доверенного токена перед просто валидным. Если его нет, то он бессмысленен, если оно все же есть (напр. больше попыток на вход и т.д.), то тогда еще вопрос — доверенный devid как-то привязывается к пользователю или нет? Если не привязывается — что атакующему мешает сделать его доверенным через вход в его собственный аккаунт и вся защита сходит на нет. Если привязывается, то это порождает множество других проблем — усложнение системы, сложность входа с одного устройства разных пользователей и т.д.

                  Вообще, это скорее не защита от брута, а защита от доса через брут, т.к. в плане усложнения перебора здесь ничего нет (любые фронтенд фичи легко обходятся естественно), а по факту только увеличение количества потенциальных слабых мест, как с примером выше. Обычно защиты от брута выглядят гораздо строже.
                  Например, хитрость с превышением лимита и т.н. «режимом атаки» легко обходится тестовыми запросами для вычисления лимита. Сам лимит в 1000 в минуту не адекватен (понимаю, что для примера, но пример не очень):
                  1. Если лимит привязан к юзеру — ничто не мешает атакующему брутить параллельно миллионы юзеров и тут даже 10 попыток в минуту может хватить чтобы сбрутить нереальную кучу юзеров/паролей.
                  2. Если лимит привязан к IP — ботнеты в помощь
                  3. Если лимит ни к чему не привязан — получаем сразу DoS всей системы выдачи devid и больше никто с нового девайса не зайдет. Включение капчи и любые другие ужесточения все равно убьют на корню всю задумку «дружественной» защиты

                  Таким образом, защита от брута получается от слова «никакая». К сожалению, ничего лучшего 2FA в этом плане пока не придумали, как вы и сами заметили. Тогда весь смысл вашей задумки все равно теряется. А приведенный пример mail.ru как раз реализован в 2FA, где ему и место.

                  Также ваша задумка «дружественной» защиты подразумевает, что пользователь не узнает, что на его аккаунт идет атака. Это тоже неверное решение. Если его аккаунт брутят, значит он скорее всего куда-то утек (либо взломаны его другие аккаунты на этом имейле, либо еще какая-то уязвимость используется), а в этом случае надо большими красными буквами писать об этом пользователю, даже если это не влияет на его текущую сессию. Надеюсь вы понимаете почему.
                  Если все же целью является только антидос логина, то предложу еще один вариант обхода. Я так понимаю, что при логауте пользователя сессия разрушается, но devid сохраняется как доверенный. Есть еще один тип атак — CSRF. Большинство сервисов имеют login/logout CSRF и не считают это за уязвимость (почем зря). Однако через логаут и последующие N некорректных логинов… ну вы поняли :) Вот такой вот CSRF DoS, причем массовый (не направленный на конкретного юзера).

                  А все это ради чего — неведения пользователя, что его атакуют? Итак пользователи слабо осведомлены о самых базовых аспектах ИБ, так мы им в этом еще поможем. Снижение нагрузки на саппорт? Отправляйте в FAQ, где жирными буквами будет написано, что если вы не можете войти в систему и это не вы превысили количество попыток — то ваш аккаунт пытаются взломать, ну и кучу советов по этому поводу, включая 2FA.
                  Мнимая безопасность часто хуже ее отсутствия… Хотя вопрос с антидосом логина считаю открытым, возможно и есть более подходящее решение.
                    0
                    Я одобрил ваш пост, потому, что вы потратили уйму времени на его написание. Пожалуй по объему он приблежается к статье. Но прошу вас потратить еще немного на прохождение ваших кейсов по схеме.

                    Да, основная задача — дать «друзьям» возможность пользоваться ресурсом даже в период атаки. Да, в зависимости от стратегии реагирования, пользователи с новых устройств будут получать, например капчу. Но «друзья» страдать будут минимум или вообще не будут. Капча будет включена в период атаки, и автрматом выключится при нормализации ситуации. А атака захлебнется из-за таких включений. Просто смысла не будет троллить.

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

                    Как я ответил выше, некоторые решения я оставил за «скобками». Уверен, что развить данную идею в части валидации токенов можно серьезно. Собственно на боевых серверах это так и сделано.

                    Что касается 2F я уже описал ее недостатки. И подчеркну еще раз, я за ее имплементацию там где это нужно.

                    Ну и посылать в faq пользователя… ну это моветон. А если ему 78 лет?
                      0
                      Но прошу вас потратить еще немного на прохождение ваших кейсов по схеме.

                      Я изучил схему еще вчера, но ответов на мои вопросы там не нашел. Я думал просто, что вы случайно или намеренно не упомянули некоторых деталей. Жаль что вы не захотели отвечать на эти вопросы, придется мне отвечать за вас.
                      Таким образом, вопрос про необходимость доверенного токена отвечен вами как — «нафиг он не нужен», потому что если выбросить элемент алгоритма «Is devid untrusted?» — ничего не изменится в работе алгоритма. А блок «Mark devid as trusted» можно заменить на «Number of attempts = 0».

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

                      Послать 1000 запросов в минуту — это захлебнуться? Чтобы атакующему выполнить дос-атаку на процесс логина ему не нужно проходить капчу. Пользователю же чтобы войти в систему это будет нужно. Ну и кто захлебнется из них? Ведь как я понимаю по вашим пространным ответам вы и не пытаетесь реально бороться с брутом, наоборот вы смягчаете защиту от брута ради «друзей».
                      А теперь ход конём: атакующий заранее постепенно генерит мильёны devid, а затем спокойненько себе брутит в свое удовольствие, попутно блокируя выдачу новых devid для всех остальных :) Не нашел где в вашей схеме есть противодействие такому поведению. В итоге: и защиту смягчили и «друзей» не спасли от доса. За двумя зайцами погонишься… Информационная безопасность это всегда баланс: нельзя просто так взять и повысить удобство, не пожертвовав безопасностью.

                      Ну и посылать в faq пользователя… ну это моветон. А если ему 78 лет?

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

                      Вывод: либо нормальная защита от брута (банально — после 3-х попыток ставим капчу), либо 2FA. И слоган — хотите стать нашими друзьями — включайте 2FA! Вот и все, не нужно ничего городить лишнего. Я думаю любой, даже самый тупой пользователь при первой же невозможности залогиниться с нового устройства без капчи, если ему написать что при включении 2FA такого не будет — с радостью включит его, или тупо забьет, т.к. 1 раз ввести капчу для него не принципиально.

                      Здесь ситуация походит на криптографию — постоянно возникают люди, думающие, что они знают что-то лучше многолетних изысканий великих криптографов, посвятивших этим самым изысканиям всю свою жизнь. Хотя я в целом рад стремлению автора сделать что-то лучшее, но все же надо более внимательно подходить к таким вопросам, тем более что вашими советами могут неправильно воспользоваться другие люди. Нельзя скопировать то, что было сделано для 2FA и применить это без этой самой 2FA. Если вы во всем этом надеетесь еще и на Security Through Obscurity, то когда-нибудь вы (или тот, кто вам доверился) за это поплатитесь нехилым сливом, и может быть вспомните мои слова. Но все же советую одуматься сейчас, чем кусать локти потом.
                        0

                        Еще раз, внимательно, пересмотрите схему. Еще раз, внимательно, прочтите комментарий мой вам и комментарии ранее. Вы найдете ответы на свои вопросы.
                        Спасибо!

                          0
                          Еще раз внимательно перечитайте мой предыдущий комментарий, там я за вас ответил на вопросы, на которые не смогли ответить вы. Жаль, что вы не умеете аргументированно обосновывать свою точку зрения, особенно в деталях, ведь я надеялся, что хабр для этого и нужен, чтобы иметь возможность сообща приходить к наиболее полному и верному решению. Тот комментарий был для того, чтобы предостеречь доверчивых людей от использования вашей схемы без 2FA, т.к. вы не смогли подтвердить или опровергнуть мои опасения о безопасности такой схемы.

                          P.S.
                          Кстати, концепцию т.н. «доверенных» токенов, можно использовать раздельно от вашей основной схемы валидных/невалидных devid, как это делается множеством сервисов. Напр. при первом успешном входе с недоверенного токена отправлять ссылку на имэйл, и при подтверждении считать его доверенным. Также это часто делают для тех юзеров, у кого отключена 2FA через СМС/OTP-токены. Но по факту это и есть 2FA, просто вторым фактором выступает не СМС и OTP, а email. И опять же не надо городить никакой другой «дружественной» мути, снижая безопасность, ведь этого уже достаточно.
                            0
                            Я не хочу тратить время на очевидные вещи. Было бы что обсуждать, обсудил бы. Предмета нет. Вы так и не поняли сути алгоритма. Это моя проблема? Думаю нет. И лично для вас его разжовывать у меня нет желания.
                              0
                              Я понял суть алгоритма еще после первого ее прочтения. И я вам конкретно пытаюсь указать на слабые места в схеме, а вы просто игнорируете все доводы, аргументируя лишь словами «нет желания» и ими подобными. Складывается впечатление, что вы написали статью на хабр лишь для галочки, но вроде блог не корпоративный, так что очень странно.
                              Если вам все же действительно нужен фидбэк и интернесны возможные негативные последствия применения вашей схемы на практике, то внимательно перечитайте все мои комментарии, готов ответить на вопросы и разжевать каждое предложение, т.к. мне не безразлична судьба тех сервисов, которые применив вашу схему могут быть уязвимы. Все мои вопросы были, в первую очередь, наводящими для вас, чтобы вы переосмыслили надежность и безопасность предлагаемого решения (безотносительно удобства, которое вы так отстаиваете, хотя не спорю, что оно тоже важно).

                              И да, если все же не захотите перечитывать — еще раз кратко: концепцию токенов, привязанных к устройствам, с которых был успешный вход (которые вы называете доверенными), используют уже очень и очень давно, но используют правильно, не ослабляя безопасность. И к вашей схеме с генерацией валидных/невалидных токенов это не имеет никакого отношения, т.к. нет никакой связи между валидностью токена и его доверенностью (выражаясь терминами из вашей статьи). Вместо того, чтобы сразу показать пользователю зашедшего с нового устройства капчу после N неверных попыток входа, вы просто предоставляете злоумышленнику уже N*M попыток (где M может увеличиваться до 1000 в минуту, если не превышать лимит). На «дружелюбность» доверенных токенов это не влияет от слова никак, поэтому выкидываем их из схемы (используя их отдельно), а затем выкидываем саму схему, т.к. она ослабляет безопасность.
                                0

                                Я готов лично вам разжевать по цене 1$ слово в дальнейших моих пояснениях. Т.к. уже сейчас я потратил на вас время, которое мне ничего не принесло, предлагаю начать с аванса 10$ на PP. Если ok, погнали. Вы сформулируете четко аргументы. По пунктам, я четко их контраргументирую. Ровно две итерации. Если хотя бы один из ваших аргументов не останется "закрыт", я вам возвращаю аванс, оплаты и плачу сверху 50$. Если вы не оплатите мои посты я об этом сообщаю тут. И вам просто будет стыдно. Думаю так будет всем интереснее и хоть какой-то смысл будет иметь.

                                  0
                                  Во-первых, вы уже упустили возможность что-то объяснить где-то комментариев 5 назад и я не прошу вас делать это сейчас, т.к. мне самому пришлось за вас все объяснять, я лишь взываю к вашему разуму, чтобы вы критически подошли к этому вопросу.
                                  Во-вторых, есть в этом мире вещи, которые не измеряются деньгами. Если бы все исследователи проводили свои исследования только за деньги, то мир был бы в гораздо большей опасности. Если уж просите оплаты за свои услуги, то зачем мелочитесь, начинать надо было, как мининум, со $100 или даже с $1000, или вы и в этом себя не уважаете?
                                  Также справедливости ради напомню, что не я разработал схему и написал эту статью, и по идее защищать ее адекватность тоже должен не я. Мое дело лишь предоставить аргументированную критику. А вы ведете себя как барин, которому негоже перед холопами что-то объяснять. Ну, успехов вам в этом деле, у меня есть дела поинтереснее, чем биться головой об пол перед таким барином.
                                    0
                                    Ясно.
                    0
                    Я для своей CMSки реализовал аналог fail2ban. При определенном количестве не верных попыток блокирую на определённое кол-во минут. Например 5 не правильных логинов — блок 30 минут. Еще вводил нарастающие паузы. Например после третьего не верного ввода в течении 5 минут, каждый последующий уходил в «паузу» на 1 секунду дольше предыдущего.

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

                    Но Вашу схему возьму на вооружение, посмотрю пригодится или нет.

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

                    Самое читаемое