Пишем защиту от брутфорса
В этой статье я покажу как защитить авторизацию с одним пользователем.
Например та же админка. Довольно важная часть
движка, которая должна быть хорошо защищена. И логин:пароль впринципе
один. Как раз нам подходит.
В этот раз мы все засунем в один скрипт + один скрипт будет дополнительным.
Ну что ж, не буду забегать вперед,
всему свое время. Вся защита будет заключаться в одном скрипте - скрипте авторизации.
Начнем с того, как будем авторизовывать
юзера. Я опять пропускаю постоянные элементы скрипта.
login.cgi:
####################conf######################
$r_login="admin";
$r_pass="12CsGd8FRcMSM";#я думаю понятно, что пасс здесь закриптован с помощью crypt().
#скрипт криптовки паролей я выложу в конце статьи
#########################
if ($login eq $r_login && crypt($pass,$r_pass) eq $r_pass)#проверяем введенные логин:пасс с
настоящими
{open (FORM, "<txt/admin.txt");#если сходятся, открываем текстовик с html-кодом админки и
выводим
@admin=<FORM>;
close FORM;
foreach (@admin){
print "$_\n";}}
Хочу обратить внимание на пароль. Самое безопасное это закриптовать его,
не стоит хранить его в открытом виде ни в файле, ни
в самом скрипте. Я думаю остальной код понятен. Что мы получаем?
Более или менее защищенную авторизацию. Но даже если юзер
введет неправильные логин или пароль, никакого бана, ничего не будет.
То есть по-человечески - возможен брутфорс. Какая первая
мысль приходит в голову? Написать счетчик неудачных авторизаций. Неплохо.
Дальше? Использовать cookies. А если запретить
в браузере или файрволе использование cookies? Тут и находится самое западло.
Дело даже не в самих плюшках, дело в том,
что нельзя брать во внимание варианты использования клиентского компютера.
Если по-человечески, все действия надо выполнять
на сервере. А если попробовать блокировку ip? Юзер может использовать проксик.
Ну или vpn. Этот вариант тоже отпадает. Что
остается? Блокировка всей авторизации. То есть, если юзер n-ное количество раз
неправильно вводит пароль/логин, то блокируется
весь скрипт. И никто уже не сможет авторизоваться, даже сам админ. Разблокировать
скрипт можно через n минут. Представим
ситуацию. Юзер собрался заняться брутфорсом. Увидел простенькую админку. А в скрипте
указано, что максимум неправильных
авторизаций - 2. Блокировка скрипта происходит на 1 минуту. Итак юзер написал скрипт,
который перебирает пароли. И получается,
что через каждые 2 неправильных пароля ему надо ждать 1 минуту. Допустим у него в
словаре 100 слов. 100/2P. Только на
блокировке он потеряет 50 минут. А если прибавить время каждого подключения, нервного
покуривания и бесконечных матюгов,
получится как раз час. Что такое для взломшика 1 час и что такое для админа 1 минута?
В этом заключается вся хитрость.
Начинаем мутить нашу защиту. Переписываем скрипт заново. Начнем с конфигурации:
####################conf######################
$r_login="admin";
$r_pass="12CsGd8FRcMSM";
$stop=2;###сколько попыток ввода пароля
$ban=1;###насколько минут действует бан
##############################################
У нас будет два текстовика: в один мы будем записывать количество неудачных авторизацией,
во второй - время сервера.
###эта подпрограмма будет очищать второй текстовик при удачной авторизации
sub clear_time{
open (TI, ">txt/time.txt");
seek TI, 0, 0;
print TI "";
close TI;}
##############
open (ST, "<txt/time.txt");##открываем текстовик со временем сервера (описание содержимого см
ниже)
@st=<ST>;
close ST;
print "Content-type: text/html\n\n";
if ($st[0]=~/.+/ && $st[1] ne (localtime)[1])
{print "BAN!!!";}#баним, пока время не истечет
else{
&clear_time();
###
if ($login eq $r_login && crypt($pass,$r_pass) eq $r_pass){
open (FORM, "<txt/admin.txt");
@admin=<FORM>;
close FORM;
foreach (@admin){
print "$_\n";}
open (OK, ">txt/count.txt");##если авторизация успешна, обнуляем счетчик и текстовик со временем
сервера
seek OK, 0, 0;
print OK "0";
close OK;
&clear_time();}
else{
open (COUNT, "txt/count.txt");###если логин/пароль неправильны, открываем счетчик
$count=<COUNT>;
close COUNT;
if ($count==$stop){##если счетчик сходится с количеством попыток,
$tim=(localtime)[1];#запоминаем время сервера
$unban=$tim+$ban;#считаем сколько банить
if ($unban>59)#
{$unban="0".($unban-60);}#
print "Fuck you, lamer!";#вот он ключевой момент!
open (ME, ">txt/time.txt");##записываем время сервера и прекращения бана
seek ME, 0, 0;
print ME "$tim\n";
print ME "$unban";
close ME;}
else
{$count=$count+1;##если попытки еще есть, увеличиваем счетчик
open (WR, ">txt/count.txt");
seek WR, 0, 0;
print WR "$count";
close WR;
print "Error!!!";}}##пишем, что скоро кое-что будет :)
###
}
########################################
Как обещал, скрипт криптовки паролей:
#!/bin/perl
print "Content-type: text/html\n\n";
$pass="password";
$key="123";
$c_pass=crypt($pass,$key);
print "pass-$pass<br>";
print "crypt pass-$c_pass<br>";
print "key-$key";
########################################
Вот и все. Если админ при заходе в админку видит заветное BAN!!!, ему
стоит призадуматься. Кто-то не равнодушен к его сайту.
Для полной секьюрности можно добавить запись логов. Но с этим я надеюсь
читатель справится. Я описал основную идею. Конечно,
довольно хардкорно, и подходит только для таких вот админок, но согласитесь,
мысль можно развить. В части 2 будем думать как
защитить многопользовательскую авторизацию, например в форуме. Ждите. Eof