Реальные истории хакерских злодейств

Ранним утром, еще до восхода солнца, у меня вдруг пискнула ася. Ожил старый приятель, с которым я не разговаривал целых три месяца. На вопрос: «Как дела?» - товарищ не ответил. Он лишь попросил меня проверить его сервер на прочность. Как выяснилось позже, его машину постоянно атаковал один и тот же хакер, оставляя после себя красочный дефейс и папку /lameroot. Мне предстояла тяжелая работа по расследованию этого преступления.

Согласись, что если человек располагает какими-либо данными (IP-адресом, багом, через который совершался взлом, и т.п.), то разобраться в ситуации - дело одного часа. С моим другом все обстояло несколько иначе: он неважно знал *nix, поэтому особо не ворошил логи Апача. В результате выяснилось, что обращения к его сайту вообще никак не логировались. Конечно, можно было наладить Web-сервер и ждать новой атаки, но я выбрал путь посложнее.

Анализируем ситуацию

Для каждой моей атаки существует причина. В этой ситуации я решил взломать сервер знакомого с одной целью - проследить за действиями взломщика и блокировать ему доступ в дальнейшем. Первое, что я сделал, - попросил товарища предоставить список правил файрвола. Через 5 минут он с горем пополам запостил мне скрипт. Дело в том, что файр устанавливал старый администратор, который профилировался исключительно на *nix. Если верить списку рулесов, файрвол закрывал все порты, кроме 21 и 80. 22 порт начисто фильтровался и был доступен только для локальной сетки. К сожалению, это все данные, которыми я располагал на тот момент.

У злобного хакерюги было два пути: ломиться на сервак либо через FTP-демон, либо через бажный скрипт. Первый вариант я отбросил сразу: версия ProFTPD была стабильной. Даже если у хакера и был приватный эксплойт, то он не мог им воспользоваться, ибо на FTP был допуск всего у двух системных пользователей. Учитывая то, что знакомый установил им сверхсложные пароли, можно сделать простой вывод - атака проводилась через web. Оставалось лишь залезть на WWW и тупо тыкать в ссылки, пока какой-нибудь скрипт не сломается под жестким напором.

Дырявый SMS

Первым делом я натравил своего осла на сайт приятеля. Контент радовал глаза: портал был посвящен online-знакомствам. Все это дело вертелось на знаменитом движке e-hoops последней версии (друг думал, что дыра затаилась в этом проекте, но переустановка до последнего релиза не помогла избавиться от назойливого хакера). Все скрипты, расположенные на этом проекте, выполнялись в одном стиле, это значит, что они поставлялись в виде специальных модулей для e-hoops. Ощупав все сервисы на сайте, я даже усомнился в том, что атака проводилась через WWW. Быть может, хакер таки откопал пароль на FTP и дефейсил сайт простым аплоадом файла? А быть может, взломщик вообще обошел файрвол и таким образом проник на сервер? От неопределенности у меня уже кружилась голова. Но тут мой взор упал на неприметный линк, ведущий к скрипту отсылки SMS-сообщений абонентам Мегафона.

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

Жаль, что я не был подключен к Мегафону :). Я не мог быть уверенным в исправности скрипта, но все же мне требовалось проверить его функциональность. Забив в поле для номера телефона рандомный мобильник и наколбасив тестовый набор символов, я нажал кнопку «Send». Спустя несколько секунд скрипт выплюнул какую-то дебаговую инфу. Приглядевшись, я узрел в ней обмен между сценарием и SMTP-сервером и понял, что скрипт просто шлет текст SMS на определенный e-mail в домене sms.megafonural.ru, таким образом добиваясь отправки сообщения. У меня лишь не укладывалось в голове, зачем нужно постить такую конфиденциальную информацию. Можно ведь просто сообщить юзеру, что текст успешно отправлен.

Внезапно у меня появилась еще одна идея. А что если скрипт не проверяет параметры на спецсимволы? Подставлять в качестве текста |id| или %00 глупо - PHP переварит их как миленький. А вот попробовать заюзать баг функции system() вполне реально. Баг проявит себя в двух условиях: если переменная не проверяется на символ «;» и если в сценарии используется системный вызов. Изначально я попробовал вставить точку с запятой в текст, но к желаемому результату это не привело. По крайней мере, вывод скрипта говорил о том, что мессага успешно отправлена. Тогда я решил вставить специальный символ в номер телефона. Но не просто вставить, а воткнуть команду перед телефоном, обрамив ее «;». В ответ сценарий вернул мне драгоценную информацию. Теперь я мог с уверенностью сказать, что хакер-негодяй, беспокоивший моего приятеля, при взломе пользовался этой веселой SMS-лазейкой. Но помимо дефейса, который взломщик мог совершить и под nobody-правами, он оставлял загадочную папку в корне файловой системы. А вот это было уже интересней. Как он это делал, я пока не знал.

Порутай через WWW

Из-за файрвола хакер никак не мог воспользоваться бэкдором. Таким образом, взломщик мог либо закачать шпионский php-сценарий, который выполнял произвольные команды, либо вообще наслаждаться дыркой в sms-скрипте без привлечения дополнительных средств. Чтобы прояснить ситуацию, я выполнил команду ls -la. К моему удивлению, Apache был грамотно настроен: все документы имели отличный от nobody UID, что не позволяло хакеру положить файл на Web. По-видимому, конф настраивал старый администратор, потому как способностей моего приятеля для настройки suexec явно не хватило. Я еще раз загрузил скрипт, чтобы узнать версию ядра. В ответ я получил число 2.4.20. Поскольку все служебные префиксы отсутствовали, стало ясно, что ядро никто не патчил и можно было добыть рута через обычный mremap-exploit. Но сплойт запускает /bin/bash, возможностями которого через WWW никак не воспользоваться. Следовательно, таинственный взломщик модифицировал сплойт и выполнял под рутом произвольную команду. Раньше я не думал об этом, но теперь у меня созрел план нового метода обхода файрвола. Оставалось только применить его на практике.

Скачав сплоит себе на винт (wwwsecurity.nnov.ru/files/mremap_pte.c), я открыл его для чтения и стал просматривать исходный код. К моему счастью, путь к шеллу был оформлен не в шеллкоде, а в отдельной переменной, что значительно упрощало мою работу. Мне понадобилось лишь видоизменить значение переменной launch на /tmp/cmd. Когда я этого добился, я создал во временном каталоге файл cmd со следующим содержанием:

#!/bin/sh

/bin/chown root:root /tmp/exec

/bin/chmod 0755 /tmp/exec

touch /owned

Теперь я бережно залил два хакерских файла в каталог /tmp. Для этого мне пришлось воспользоваться командой curl, поскольку любимого wget’а на сервере не было. Я начал собирать эксплойт, но тут возникла неожиданная проблема - он почему-то не захотел компилироваться. Мне было влом разбираться, в чем дело, и я выполнил это нехитрое действие на другой машине, а затем просто портировал файл. После запуска злостного munremap'а в корне успешно создался файл /owned. Можно сказать, что все шаги моего злодейского коллеги уже были раскрыты, но азарт заставил меня доработать метод выполнения рутовых команд через WWW.

Пишем свой интерпретатор

Ты, наверное, не понял, почему в листинге скрипта /tmp/cmd промелькнул загадочный /tmp/exec. Дело в том, что мне захотелось написать собственный интерпретатор, при обращении к которому выполнялась любая команда от пользователя root. Для этого мне пришлось написать одну элементарную программу на си, а затем скомпилить ее в /tmp/exec. Прога должна обладать всеми функциями интерпретатора, а запрос читать из произвольного файла. Изучи исходник моего творения, быть может, ты сам не раз к нему обратишься :).

Exec.c - рутовый интерпретатор

#include <stdio.h>

int main() {

FILE *file; /* Файловая переменная */

char cmd[200]; /* 200 символов для команды должно хватить за глаза */

setuid(0);

setgid(0); /* Изменяем уид на 0 */

file=fopen("/tmp/c","r");

fgets(cmd,sizeof(cmd),file); /* Вытаскиваем из файла /tmp/c рутовую команду */

system(cmd); /* И выполняем ее */

fclose(file);

}

Можно было поступить проще и оформить команду в виде аргумента к шеллу, но мне удобнее записывать запрос во временный файл. Оставалось залить мой интерпретатор в /tmp/exec.c и собрать самопал компилятором.

Теперь, когда мне требовалось выполнить рутовую команду, я забивал ее в файл /tmp/c, а затем запускал /tmp/exec. Перед воплощением идеи в действительность я повторно стартанул эксплойт, для того чтобы он засуидил /tmp/exec.

Ставим капканы

Даже после проверки метода на практике я не остановился на достигнутом. Мне хотелось удивить приятеля и доказать ему, что даже через Web хакер может натворить ужасные вещи. Я вбил в качестве команды строку /etc/init.d/iptables stop, которая должна деактивировать брандмауэр. Переварив злую команду, скрипт радостно сообщил, что таблицы iptables стали пустыми :). Далее я прителнетился на 22 порт, и... сервис без проблем выдал свой баннер. Остальные действия я проводил на автомате: создал юзера с 0 уидом (простой дозаписью в /etc/passwd и /etc/shadow), а затем залез по SSH в систему. Надо отметить, что опция PermitRootLogin была почему-то включена и это позволило мне проникнуть на сервер под суперюзером.

Если верить знакомому, хакер появлялся на его сервере примерно раз в неделю. Я решил не фиксить самопальный скрипт, чтобы подловить негодяя. Поэтому я ограничился тем, что включил логирование всех web-запросов.

Наступил вечер. Я поговорил с товарищем, который сердечно поблагодарил меня за помощь в расследовании. Узнав про баг в SMS-скрипте, друг разделил мое мнение, решив, что фиксить брешь пока не следует. Как выяснилось, он попросил какого-то программера написать ему перловый сценарий, который слал бы произвольный текст на определенный e-mail. Затем, когда другу захотелось украсить свой сайт, он интегрировал sms.php и перловую поделку. В результате получилось вот что: сценарий обрабатывал входные переменные, затем приплюсовывал к номеру «@sms.megafon.ru» и писал текст сообщения в файл. Финальной строкой был, конечно же, системный запрос к sms.pl, который принимал следующий вид: system("perl ./sms.pl номер@sms.megafon.ru"). Интерпретатор заставлял считывать временный файл с сообщением и засылать текст получателю. А вывод дебаг-инфы был обусловлен тем, что мой приятель захотел протестировать работу системы, а обнулить переменную $debug в файле sms.pl, как водится, забыл. Все эти недоработки и отсутствие какой-либо проверки данных привели к фатальному результату.

Через несколько дней, когда я уже запамятовал о проверке сервера, приятель снова вышел на связь. Он сказал, что хакер снова оставил дефейс и папку /lameroot :). То есть действовал по своей привычной схеме. Вот дурачок :). Я тут же попросил оформить мне SSH-доступ, чтобы выудить из логов важную информацию. Я не ошибся, взломщик действительно нашел брешь в SMS-скрипте. Как выяснилось позже, он заливал скомпиленный mremap.c с интегрированной в него командой, а когда злоумышленнику хотелось выполнить другой запрос, он тупо пересобирал сплоит. Самое главное, что горе-хакер не использовал проксика, и его адрес говорил о том, что нарушитель является клиентом сети крупного московского провайдера. Впоследствии мой приятель написал телегу в саппорт, и дефейсы прекратились. Впрочем, возможно, они прекратились из-за того, что он воткнул проверку на символ «;» в sms.php. Ибо нефиг :).

Где здесь мораль?

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

Что помогло мне при взломе?

1. Имея нюх на подозрительные скрипты, я быстро нашел лазейку на Web’е даже при выключенном журналировании запросов.

2. Для удобства я написал простенький интерпретатор, который позволял мне выполнять любую рутовую команду. Можно было пойти другим путем - каждый раз заливать эксплойт с вкомпиленной внутрь командой (именно так и делал хакер-дефейсер). Но мой способ реализуется намного быстрее.

3. Чтобы на скорую руку добавить нового пользователя, мне было достаточно запустить две команды: первая дозаписывала служебную информацию в /etc/passwd, вторая - логин и пароль в /etc/shadow.

INFO

Чтобы хакер не смог войти на сервер под нулевым уидом, поставь значение No у опции PermitRootLigin. А также деактивируй PermitEmptyPasswords. На всякий случай ;).

INFO

В некоторых версиях эксплойта mremap.c приходится ждать 4 часа до результата взлома. Если ты столкнулся с таким релизом, ищи обновление - более продвинутый сплойт ломает ядро всего за пару секунд.

CD

На диске ты найдешь все прикладные средства, которые применялись при проверке, а также увидишь видеоролик, визуально восстанавливающий все интересные события.

Warning

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