Неотъемлемой частью «защиты информации» является защита web-контента. Поэтому вебмастеры должны не только уметь грамотно управлять сайтом, но и уметь его защищать от разной нечисти вроде скриптиддисов и флудеров, которых сейчас развелось полным полно в Сети. Сегодня мы побудем в роли плохих парней. Вместе мы рассмотрим основы процесса зафлуживания web-приложений. Узнаем тонкости автоматизации «наводнения» на примере самопального форумного движка и напишем для него свой полнофункциональный флудер. Итак, приступим!

[первые шаги]

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

1) Скрипт для отображения сообщений (gb/index.php)

2) Форма для отправления сообщений в книгу (gb/from.html)

3) Скрипт для записи нового сообщения в гостевую (gb/script.php)

То есть, если ты хочешь оставить свою запись в чьей-нибудь гостевой книге, то поочередно обращаешься к следующим документам: form.html (забиваем наши данные) -> add_mess.php (наши данные передаются скрипту для записи в БД или файл) -> index.php (теперь здесь будет отображаться наш коммент к гостевой книге).

Чтобы понять, каким образом можно засыпать приложение левыми сообщениями, давай посмотрим, как выглядит стандартная форма для отправки сообщения:

[среднестатистическая форма для отправки сообщения]

<form action=script.php method=POST>

Имя:

<input type=text name="your_name" ></><br>

Адрес e-mail:

<input type=text name="email" ></><br>

Твой комментарий:

<textarea name="text" rows=10 cols=65 >

</textarea><br><br>

<input type=Submit >

</form>

Как только ты нажмешь на кнопку Submit, данные тут же передадутся серверному приложению при помощи POST-запроса, внутри сценария создадутся переменные $_POST[your_name], $_POST[email], $_POST[text] и эти данные запишутся в базу данных или текстовый файл.

А теперь представь на секунду, что будет, если начать методично нажимать ctrl+r, отправляя на сервер все новые и новые сообщения, заполнив таким образом за пару минут гостевую книгу десятками сообщений. Чтобы не допустить такого поворота событий, сейчас все скрипты оборудованы той или иной защитой от флуда и такая элементарная атака не проходит.

Сейчас мы научимся обходить некоторые защиты и, самое главное, автоматизируем процесс флуда. Как? Конечно же с помощью любимого скриптового языка - Perl.

[собираем паучка]

Допустим, ты хотел заполнить гостевуху своего недруга сотней-другой веселых и полезных сообщений. Разумеется, этот процесс было бы неплохо поставить на конвейер. Для этого нам нужно наколбасить перловый сценарий, который будет сам заходить на страницу и оставлять сообщение. Perl-скрипт может работать с web через сокеты, но намного легче использовать специально заточенный для этих целей модуль LWP (library WWW for Perl). Он должен быть прикручен к перлу по умолчанию. Вот как будет выглядеть примитивный флудер для нашей многострадальной гостевой:

[примитивный флудер]

#!/usr/bin/perl

use LWP::UserAgent;

use HTTP::Request;#этот модуль нам необходим, чтобы создавать «запросы» вида ( метод=>"урл" );

$url="www.sobakoff.net/script.php";

$name="Sashiks";#Это наши данные. которые будут отправляться

$email="real_sshx@mail.ru";

$text="Это не флуд! ";

$opera=LWP::UserAgent->new();#Создаем новый объект - браузер;

$req=new HTTP::Request(POST=>"$url?your_name=$name&email=$e mail&text=$text");#создаем новый запрос

$opera->request($req);#Выполняем запрос, то есть отправку данные скрипту

print"Message added!\n';

После запуска этого скрипта в гесте должна появиться наша запись. Чтобы отправить больше сообщений можно просто добавить цикл, где счетчиком будет число необходимых тебе сообщений. Правда просто? Кстати, в Perl есть еше один модуль из семейства HTTP. Он создан специально, если тебе нужно часто работать с web-формами. Подключается он так: use HTTP::Request::Common, а запрос из предыдущего примера реализуется следующим образом:

$req=POST('www.sobakoff.net/script.php', [your_name=>'$name', email=>'$email', text=>'$text'] );

Здесь в квадратных скобках мы просто присвоили необходимым параметрам соответствующие значения.

[копаем глубже]

Разобравшись с основами «затопления» вражеских гестбуков можно перейти к более интересному занятию - изучению форумов и разработки полноценного автономного флудера. Между прочим, за это дело я взялся не зря. А все потому, что мой британский друг Кайл (фанатик юниксов), однажды забрел на сайт wwwlinuxsucks.org, где ему очень не понравилось тамошнее отношение наглых буржуев к детищу Линуса Торвальдса (да и никсам вообще). Так как сайт по сути представлял собой один большой форум, я тут же получил задание сделать им какую-нибудь пакость - например, до опупения залить их топиками, вроде Kill Bill(Gates) . Вот такая вот прелюдия. Теперь на примере wwwlinuxsucks.org мы будем писать нашу программу. Сейчас я расскажу, как я изучал этот форумный движок. Первым делом я, конечно же, зарегался и зашел в раздел discussions. Сайт был построен на php (хотя файлы и были замаскированы апачем под *.html). Я выбрал произвольный топик и стал смотреть сообщения в нем. В самом конце списка ответов была кнопочка AddReply. После нажатия меня перебросило к форме для ответа на пост. Ничего особенного в ней не было - поле для темы, текстовое поле и кнопка для отправки Post. Я заполнил поля какой-то лабудой и нажал на Post, но тут надпись на кнопке изменилась на что-то, вроде «Подождите. Идет обработка» (сама кнопка стала теперь неактивной), и лишь потом мне вывели новую страницу и сообщили, что ответ успешно записан. Мне стало интересно, смогу ли я вернуться и запостить сообщение заново, поэтому в браузере я перешел на страницу назад. Все поля были заполнены и не очистились, но еше раз запостить этот ответ я не мог, потому что кнопка Post так и оставалась неактивной. Вот это первый вид защиты от флудеров. Теперь я решил оставить еще один ответ, и как только мне сообщили, что сообщение добавлено, я тут же вернулся к тому топику и опять нажал AddReply и увидел форму для ответа. Я быстренько ее заполнил и нажал Post. Но теперь на загрузившейся страничке вместо ожидаемого «Ответ успешно записан» появилось предупреждение о том, что запрещено оставлять более одного сообщения в минуту. Как видишь, еще один прием защиты от попадания в форум всякого мусора. Что ж, для начала неплохо, но я знал, что в форме должен был быть еще какой-то трюк, чтоб защититься от флудеров. Так и оказалось. Если просмотреть html-код страницы, то можно увидеть несколько скрытых полей, в которых передавались параметры, среди которых были topictitle (название темы), postid (ID номер топика) и некий неизвестный параметр token. А вот на нем я хочу остановиться поподробнее. Лично мне он напомнил MD5 хэш: <input type="hidden" name=token value="95fcc3baff27ce6c2c3e7afd4303b7cb">.

Так, скорее всего, и было (причем я заметил, что хэш генерировался каждый раз новый и не от чего не зависел). То есть при генерировании web-формы для ответа на пост в нее вставляется сгенеренный хэш, и как только мы жмем кнопку Post, то скрипт, которому передаются параметры, сравнивает значение, переданное ему в $token, с тем, что было вставлено в форму. Если же значения не совпадают, то ответ просто-напросто не записывается. Немного почесав репу, я понял, что для создания флудера под форум, этих данных будет мало. Мне нужно было знать все значения (в том числе и в скрытых полях), которые передавались из формы. Для этого мне нужно было сохранить форму на себе на винт и в html-коде исправить:

<form onSubmit="submitonce(this)" action="/addReply.html" method="POST" enctype="multipart/form-data">

на

<form onSubmit="submitonce(this)" action="http://www.linuxsucks.org/addReply.html" method="GET" enctype="multipart/form-data">

То есть в action я прописал полный путь к скрипту, а метод передачи заменил на GET. Теперь, нажав на Post, страница начнет передавать на сервер данные, но теперь методом GET, поэтому в адресной строке браузера я смогу увидеть все параметры. Вот как выглядела эта строка:

wwwlinuxsucks.org/addReply.html?xtitle=название_нашего ответа&postid=это_номер топика&topictitle=название_самого_топика&xmsg=наш_ ответ&Post=Post&token=это_md5_хэш&mode=Submit.

Параметры post и mode не менялись в зависимости от топика. Теперь, получив все необходимые сведения, я уже мог начинать писать флудер.

[перловые забавы]

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

1)Аутентификация на сайте (логин+пароль)

2)Получение Cookies

3)Получение страницы с формой (парсинг параметров)

4)Составление запроса (плюс Cookies)

5)Отправка запроса

Сейчас мы разберем каждый пункт. Первое, что нам нужно сделать - пройти авторизацию с помощью пары «логин:пароль». Если этого не сделать, то при запросе страницы с формой нас все равно перебросит на пагу login.html. Благо авторизация выполнена крайне просто в виде двух полей, поэтому, чтобы нас впустили, достаточно проделать следующие:

$opera=LWP::UserAgent->new();

$req=new HTTP::Request(POST=>"http://www.linuxsucks.org/login.html?xlogin=$user&xpassword=$pass");

$response=$opera->request($req);Я подразумеваю, что юзер зареган, и логин с пассом валидны. После этого нам должны выдаться куки. Но как их сохранить для дальнейшего использования? Для этого нам нужно подключить модуль use HTT::Cookies. Вот основные методы для объектов:

$cookie_jar=HTTP::Cookies->new(); #мы создаем псевдо БД, где будут храниться печенья. Кода сессия заканчиваеться, БД опустошаеться.

$cookie_jar->extract_cookies($response); #Из полученного браузером ответа (см.выше) мы извлекаем кукис и кладем его в нашу БД

$cookie_jar->add_cookie_header($request); #Присоединяем наш файл cookie к запросу $request (об этом далее).

То есть после авторизации приходит ответ сервера, в котором мы получаем Cookies. Эту куку бережно сохраняем в $cookie_jar, ведь она нам позже пригодится (к слову, нам ее нужно цеплять к каждому запросу). А сейчас нам надо получить hrml-код страницы с формой для ответа. Допустим, если ты хочешь наводнить топик с ID 1500, то это будет выглядеть примерно так:

$req=new HTTP::Request(GET=>"http://www.linuxsucks.org/addReply.html?postid=1500");

$cookie_jar->add_cookie_header($req);# вот здесь мы прикрепляем кукис, который получили при авторизации

$response=$opera->request($req);

$resp_cont=$response->content;

Сейчас в переменной $resp_cont должна храниться вся страница с формой для реплая. Мы получили ее, чтобы найти скрытые параметры такие, как token и topictitle. Если же мы не узнаем их значение, то не сможем запостить ответ. Пропарсив страницу, мы получили необходимые данные, и теперь готовы отправить запрос с нашим ответом:

$flood_post=new HTTP::Request(POST=>"$f_url?xtitle=$title&postid=$ top_id&topictitle=$topic&xmsg=$msg&Post=Post&token =$token&mode=Submit");#формируем запрос с ответом

$cookie_jar->add_cookie_header($flood_post);#опять цепляем куки

$opera->request($flood_post);#выполняем запрос

Если ты внимательно читаешь статью, у тебя должен возникнуть вопрос, что такое $title $msg и где они определяются. Все предельно просто - это название твоего ответа и его текст. Они находятся на нашем флудере, и чтобы изменить их, воспользуйся любым текстовым редактором. Вот основной текст программы без функций:

auth($auth_url); #функция авторизации

for($n=0;$n<$hmt;$n++){#$hmt - количество постов, которые мы хотим отправить ( по умолчанию 50 )

flood($rep_url); #функция для постинга наших флудерских "ответов"

sleep($def_time);

}

Ты, наверное, заметил, что в конце цикла есть запись sleep($def_time). Сейчас я все объясню. Помнишь я говорил, что скрипт ругнулся, что нужно подождать 1 минуту, когда я попытался оставить два поста подряд? То есть между постами должна быть пауза, определенная в переменной $def_time . И хоть она по умолчанию равна 60 сек, можешь проиграть с этим значением, потому что скрипт нагло врал относительно 1 минуты - на самом деле достаточно 15-20 секунд (а может и того меньше).

[the lessons is over. Goodbye!]

Ну вот собственно и все, что я хотел сказать по этому поводу. Только что мы с тобой рассмотрели основные аспекты зафлуживания в web и написали простенький академичный флудер. Надеюсь, ты его не будешь использовать даже в ознакомительных целях, потому что сильно рискуешь попутно ознакомиться с сотрудниками местного управления «Ку» . Счастливо!

[защищайтесь, сударь!]

Существуют много способов защиты web-приложений от подобного рода flood-атак. Это и скрытые таблицы и генерация произвольного кода в теле страницы. Сюда также относиться IP блокировка, шифрование с помощью JavaScript. Вообще, примеров много, и все они заслуживают твоего внимания. Очень подробную и интересную статью по этому поводу написал Said в последнем (№3) выпуске Mazafaka E-zine. Настоятельно рекомендую почитать этот материал.

[зачем это нужно?]

В самом деле, кому и зачем может понадобиться флудер? Ну во-первых, его можно использовать в корыстных целях: рекламировать что-нибудь, пиарить свой сайт, обливать грязью своего друга Петровича и так далее. Можно признаться в любви, поздравить маму с днем рождения, довести админов до белого каления. Но самое главное - помни, что грамотно реализовать защиту со своей стороны, можно лишь с головой погрузившись в проблему нападения.