Intereting Posts
UTF-8 для кодовых точек Юникода Есть ли причина использовать ключевое слово «public» перед именами переменных метода и члена? Почему Phing запускает мой файл build.xml, а затем говорит, что его не существует? Возможно ли ссылаться на столбец, отличный от 'id' для JoinColumn? как извлечь данные из url как facebook в asp.net mvc3? PHP Javascript? Сделайте что-то, когда пользователь закрывает страницу или браузер Своевременный интервал для извлечения данных из db и остановки при поступлении данных Разрешения файла и CHMOD: Как установить 777 в PHP при создании файла? Получить первое слово в строке php the_title WordPress Стратегия кэширования, когда кеширование становится бессмысленным? Что такое обработчик сериализации php_binary? Добавление и доступ к идентификаторам кнопок в таблице, сгенерированной PHP php array_filter без сохранения ключа Laravel отношения на столе с двумя типами флагов Как загрузить фотографии в альбом с помощью API-интерфейса Facebook Graph

Предупреждение грубой силы / DoS в PHP

Я пытаюсь написать сценарий, чтобы предотвратить попытки входа в грубую силу на веб-сайте, который я создаю. Логика выглядит примерно так:

  1. Пользователь отправляет регистрационную информацию.
  2. Проверьте правильность имени пользователя и пароля
    • Если да, включите их.
    • Если «Нет», запишите неудачную попытку в базе данных. Проверьте, нет ли слишком много сбоев в течение заданного периода времени (например: 5 за 5 минут):
      • Если «Да», то приостановите выполнение в течение 10 секунд: sleep(10) , а затем сообщите пользователю о неудаче входа в систему.
      • Немедленно сообщите пользователю о неудаче входа в систему

Объясняя это сотруднику, меня спросили, как это поможет, если хакер отправит, скажем, 1000 запросов за одну секунду. Будут ли первые 5 возвращаться сразу, а остальные оставшиеся 995 займут всего 10 секунд?

У меня есть подозрительное подозрение, что я не совсем понимаю, как работает HTTP – эта ситуация выше, чем возможно, или существует ли ограничение на количество одновременных запросов, которые сервер будет обрабатывать с одного клиента?

Будет ли лучшее решение иметь увеличение времени сна?

 sleep($numRequestsInLast5Minutes - 5) 

Таким образом, первые 5 будут быстрыми, а затем каждый последующий будет увеличивать сон.

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

Первое решение

 If not password correct for a certain number of time: block the user send a reset link to the user 

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

Второе решение

 If not password correct: sleep(amount_of_time) 

Вопрос в следующем: какова ценность «amount_of_time»?

Пользователь : может быть досадно ждать «amount_of_time» для каждой ошибки
Атакующий : продолжайте попытки, с более низким тестом / секундой

Третье решение

 If not password correct: sleep(amount_of_time) amount_of_time = amount_of_time * 2 

Пользователь : меньше раздражает за несколько ошибок пароля
Атакующий : заблокируйте пользователя для соединения, отправив много неправильного пароля

Четвертое решение

 If not password correct for a certain number of time: submit a catchpa 

Пользователь : нужно разрешить CAPTCHA (не слишком сложно)
Атакующий : необходимо разрешить CAPTCHA (должно быть сложно)

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

Пятое решение

 If not password correct for a certain number of time: block the ip (eventually) send a reset link 

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

Окончательное решение ?

 If several login attempts failed whatever is the user by an IP : print a CAPTCHA for this IP 

Пользователь : пользователь не может быть заблокирован IP-адресом, но должен помнить пароль.
Атакующий : трудно иметь эффективную атаку грубой силы.

Важные примечания

Является ли форма входа или ссылка на вход в систему, которая заблокирована? Блокирование формы входа бесполезно.

Устойчивость к грубой силе является ПЕРВОЙ проблемой сложности пароля, поэтому вам нужна строгая политика паролей (особенно в случае распределенной грубой силы).

Я не упоминаю факт, чтобы хэш ваши пароли с солью, вы уже делаете это правильно? Потому что, если легче получить доступ к базе паролей, чем грубая форсировка, злоумышленник выберет это решение ( «Цепочка только сильна, как ее слабая ссылка» ).

Я бы посоветовал, если пользователь пробовал безуспешно, скажем более пяти раз и пяти минут, вы сразу же возвращаете 503 Service Unavailable для этого IP-адреса. Когда вход завершается с ошибкой, вы можете использовать memcache, чтобы получить текущие неудачные попытки для IP-адреса, а затем увеличить сумму и сохранить ее обратно в memcache с истечением 5 минут.

Вы не хотите sleep в своем PHP-коде, так как это позволит одному пользователю создавать множество подключений к вашему веб-серверу и потенциально сбивать других пользователей.

Поскольку пользователь не вошел в систему, у вас нет файла cookie сеанса, и если пользователь пытается перевести его в учетную запись, они могут вообще не представлять файл cookie.

Я использовал что-то вроде этого …

  1. Проверьте имя пользователя и пароль

    1.1 Если нет совпадения, запишите последнее неудачное время входа для этой комбинации и количество неудачных входов.

    1.2. Каждый сбой заставляет ждать, когда вы сможете войти в систему, например, failCount * 30 секунд, до максимума (например, 10 минут).

  • Это означает, что атака грубой силы будет экспоненциально занимать больше времени и дольше.
  • Он может заблокировать пользователя – но он не будет считать неудачный логин, пытаясь войти в систему в течение периода блокировки. Это должно свести к минимуму его.

Я разработал это, но не выпустил его в дикую природу, поэтому любая обратная связь будет оценена по достоинству.

Я создал класс, который заботится о защите от грубой силы в PHP.

https://github.com/ejfrancis/BruteForceBlocker

он регистрирует все сбойные логины на всей территории страны в таблице db, и если количество неудачных логинов за последние 10 минут (или любой другой временной интервал, который вы выберете) превышает установленный предел, он обеспечивает временную задержку и / или требование капки перед тем, как войти в систему снова.

пример:

// создаем массив настроек дроссельной заслонки. (# Recent failed logins => response).

$ throttle_settings = [

  50 => 2, //delay in seconds 150 => 4, //delay in seconds 300 => 'captcha' //captcha 

];

$ BFBresponse = BruteForceBlocker :: getLoginStatus ($ throttle_settings);

// $ throttle_settings – необязательный параметр. если он не включен, будет использоваться массив настроек по умолчанию в BruteForceBlocker.php

switch ($ BFBresponse ['status']) {

 case 'safe': //safe to login break; case 'error': //error occured. get message $error_message = $BFBresponse['message']; break; case 'delay': //time delay required before next login $remaining_delay_in_seconds = $BFBresponse['message']; break; case 'captcha': //captcha required break; 

}

Я не уверен, что такое лучшая практика, но при работе с DoS-атаками лучшей стратегией является отключение трафика от вашего сервера. Настройка тайм-аутов на самом деле не поможет, поскольку вы все еще обрабатываете запрос и запускаете PHP.

Рассматривали ли вы настройку другого веб-сервера, на котором была запущена упрощенная версия вашей страницы входа? Когда пользователь пытается слишком много раз (например, тысячи раз), отправьте сообщение, чтобы настроить маршрутизатор и перенаправить этого пользователя на второй веб-сервер.

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