6

Хочу сделать защиту от перебора паролей (метод «грубой силы») в моей системе на PHP для Панели Администратора. У меня уже стоит CAPTCHA, но это не защищает. Хочу сделать таймаут. Ввел 5 раз не правильно пароль — отдыхай 12 часов. Проблема вот в чем: просто так отследить компьютер-то не получается, IP у многих динамичный, а Cookie легко удаляются. Писать в БД «для всех» тоже не хорошо: вдруг кто-то просто так захочет побаловаться, а администратор потом будет сутки ждать.

Есть, конечно, другой вариант: ставить таймаут после каждого ввода пароля секунд на 5, так, чтобы сильно замедлить брутфорс + можно после 100 неправильных паролей отсылать на email владельцу сайта письмо, мол, пытаются взломать.

Что Вы думаете об этом?

9
  • "Другой" вариант больше нравится:) Только колво попыток вы в базу записывать собираетесь?
    – atnartur
    4 сен 2012 в 15:54
  • Да. Но это так, в дополнение. Без блокировок. 4 сен 2012 в 15:55
  • А если так: при 10 неудачных попытках, пароль сбрасывается и ставиться новый, который отправляется вам на email.
    – atnartur
    4 сен 2012 в 16:16
  • А как это реализовать? т.е чтобы можно было вводить пароль только каждые 5 сек?
    – qiwi
    4 сен 2012 в 16:27
  • 2
    И, да, 100 провалившихся попыток авторизации — это слишком много. Можно ошибиться раз, два или три. Раскладку, там, не переключить, например. Можно, если голова плохо соображает, даже 5-6 раз. Но больше десятка — это уже плохой признак. И уже более, чем достаточный, чтобы послать сигнал администрации.
    – drdaeman
    4 сен 2012 в 20:52

6 ответов 6

6

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

Для этого на сервере, при каждой попытке авторизации:

  1. Проверяем время последней неудачной попытки входа. Если дальше, чем час назад — переходим к п.5.
  2. Запоминаем в сессии время начала запроса.
  3. Отдаем страницу «пожалуйста, подождите», которая всеми средствами (<meta http-equiv="Refresh" ...>, javascript, ручная ссылка «обновить») обновляет себя.
  4. При каждом обращении смотрим, прошло ли 10 секунд с начала операции. Если не прошло — см. п.3, если нет — п.5.
  5. Выдаем результат авторизации, если успешно — логиним пользователя, если нет — запоминаем время неуспешной авторизации и назад на форму входа и от нее снова начиная с п.1.

Брутфорс на скорости в меньше десятка паролей в минуту быстро перестанет быть интересным. Легитимный пользователь же подождет свои 10 секунд и успешно залогинится.

Всякое security through obscurity типа входа по GET-параметрам не рекомендую. Оно будет или не сильно полезным или вредным (ссылка для входа останется в истории браузера и будет регулярно вылезать автокомплитом — прекрасная вещь для демонстрации гостям).

3
  • Мне нравится ваш вариант, я его возьму на заметку, но не буду реализовывать пока не будет необходимости. Я как раз хотел использовать GET, но не просто статичный параметр, а динамичный, который будет создаваться на некоторое время, когда система будет замечать попытки брутфорса и отсылаться на почту. 5 сен 2012 в 15:55
  • Трудность в том, что я не знаю, как отдавать страницу. Я использую AJAX для логина и будет не удобно генерировать страницу. 5 сен 2012 в 16:06
  • @cheremushkin: Покажите что и как сейчас есть, и кто-нибудь наверняка посоветует что можно сделать. Проблем не вижу никаких, что страницы выдавать, что ответы для «AJAX» — все одно и то же, обработка HTTP-запросов. Просто вместо ответа об удачном или неудачном входе предусмотреть еще ответ «нужно подождать» и с клиентской стороны его обрабатывать. Конкретику, не видя конкретики, разумеется, сказать сложно.
    – drdaeman
    6 сен 2012 в 0:16
1

Во первых стоит сделать защиту от чрезмерно частых запросов страниц. Во вторых предложу такой вариант: записывать в файл или еще куда id пользователей и время подбора и удваивайте таймаут ввода пароля вплоть до 24х часов.

Данный способ рекомендовали на хабре но для несколько других целей.

0

Динамический IP - на самом деле небольшая сказка. Он по факту не меняется при каждом переподключении, даже на диалапе (который, как я думаю, отсутствует в наше время). Плюс можно использовать уникальный ключ (md5 от юзерагента, IP, еще каких-либо данных)

1
  • У меня меняется, например. Не гербалайф^W диалап. Хотя можно фильтровать не по IP, а по подсети или вообще номеру автономной системы. А вот такой «уникальный ключ» позволит брутфорсящему даже IP не менять, а просто стучаться каждый раз с новым User-Agent. Т.е. не улучшит, а ухудшит ситуацию.
    – drdaeman
    4 сен 2012 в 20:48
0

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

1
  • Ха, я как раз придумал этот вариант перед сном. Я буду генерировать специальный хэш код, который будет активен некоторое время и будет предоставлять "черный вход" админу, чтобы зайти без проблем в систему и заблокировать на время "парадный вход". Хэш будет знать только админ, т.к. он будет приходить ему на почту. 5 сен 2012 в 15:52
0

Давно писал такую штуку, покопайте

session_start();
$time = time();

### Разрешать запросы
# Не чаще чем
$max_n = 5; # раз
# за
$max_t = 10; # секунд

if(empty($_SESSION['ban']['time'])){ $_SESSION['ban']['time'] = $time; }
if(empty($_SESSION['ban']['rate'])){ $_SESSION['ban']['rate'] = 1; }
if($_SESSION['ban']['time']+$max_t < $time){
  unset($_SESSION['ban']);
  echo 'true';
}else{
  if($_SESSION['ban']['rate'] > $max_n){
    echo 'false';
  }else{
    $_SESSION['ban']['rate']++;
    echo 'true';
  }
}
3
  • Этот код дает ложное чувство защиты. Он защищает от легитимного пользователя в браузере, и не защищает от настоящего атакующего, желающего перебрать пароли. Атакующий не будет предоставлять сессионный идентификатор (в простейшем случае достаточно банально не принимать cookies) и спокойно будет перебирать на максимальной скорости, ничем не ограничиваясь.
    – drdaeman
    12 сен 2012 в 0:49
  • Это же для примера >< Я скинул чтоб был ясен алгоритм, сам давно переписал код для MySQL
    – Fangog
    12 сен 2012 в 0:50
  • MySQL там или $_SESSION — разницы нет. Речь не о хранилище данных. Речь о том, что ограничивать нужно по правильному объекту(ам). И по пользовательской сессии, как у Вас, это бесполезно, и даже больше — вредно. По аккаунту, в который логинятся — полезно. Или по IP, например — полезно, чтобы избежать массового брутфорса одним паролем кучи аккаунтов («авось у кого-то, да "12345"»). Я тут набросал по-мелочам относительно универсальный кусок кода. Ему только массив со временами подавать — что попыток авторизации в один аккаунт, что с одного IP.
    – drdaeman
    12 сен 2012 в 1:35
-3

А ещё вот так можно сделать: Как защитить админку сайта?

То есть - вход только по get запросу. Если его нет - тогда пусть выходит чистая страница. И так вообще не понятно будет что это такое.

3
  • 1
    Вот чего автору только не хватает, так это светить эту ссылку с GET-запросом, содержащим логин-пароль, в истории браузера. Дрступ с чужих компьютеров это затрудняет (форму хоть обычно спрашивают запоминать или нет), да и домой гостей водить надо осторожно — автокомплит засветит пароль легко и непринужденно.
    – drdaeman
    4 сен 2012 в 20:40
  • Ну а если под приватной вкладкой? Можно же сразу после авторизации запоминать в сессии и потом убирать данные из get.
    – atnartur
    5 сен 2012 в 9:40
  • Можно, конечно, и еще все делать вообще из отдельной виртуалки… но зачем? А адрес, когда админ ввел (тем или иным способом) и перешел по нему, в историю уже лег, то, что потом будет редирект, уже ничем не поможет безопасности.
    – drdaeman
    5 сен 2012 в 14:35

Ваш ответ

By clicking “Отправить ответ”, you agree to our terms of service and acknowledge you have read our privacy policy.

Всё ещё ищете ответ? Посмотрите другие вопросы с метками или задайте свой вопрос.