Задача
Добавить поддержку Oracle в Metasploit
Решение
Сегодняшний Easy Hack будет во многом посвящен трикам с базами данных Oracle, так что мы начнем с чисто технической проблемы — добавим поддержку Oracle в MSF.
В MSF есть приличный набор различных модулей для атаки на Oracle, вот только из коробки они не работают. Причина тому — отсутствие необходимых либ (OCI), которые MSF не может приложить из-за лицензионных проблем. А потому мы сами должны все качать с сайта Oracle (соглашаться с лицензией) и настраивать. Процесс этот не всегда прост и гладок, кое-какие мануалы есть в Сети, но зачастую они нерабочие. Поэтому я оставлю здесь опробованные последовательности действий.
Общий алгоритм таков:
- Качаем и ставим Oracle Instant Client, а именно архив Basic, SDK и SQL*Plus.
- Прописываем в ОС необходимые переменные окружения.
- Ставим OCI-драйвер для Ruby от Metasploit’а.
Итак, точная последовательность для Kali:
- Желательно обновиться до последней версии Kali:apt-get update apt-get distr-upgrade
- Ставим ruby-dev.
- Качаем клиент (как минимум 11-ю версию)
- «Устанавливаем» (xxx — версия клиента)cd opt/ mkdir oracle cd oracle/ unzip basic-xxx-linux.zip unzip sdk-xxx-linux.zip unzip sqlplus-xxx-linux.zip cd instantclient_xxx/ ln -s libclntsh.so.xx.x libclntsh.so wget https://github.com/kubo/ruby-oci8/archive/ruby-oci8-2.1.5.tar.gz tar -zxvf ruby-oci8-2.1.5.tar.gz
- Прописываем instant client в переменные окружения:echo "export PATH=$PATH:/opt/oracle/instantclient_xxx" >> /root/.bashrc echo "export SQLPATH=/opt/oracle/instantclient_ xxx" >> /root/.bashrc echo "export TNS_ADMIN=/opt/oracle/instantclient_ xxx" >> /root/.bashrc echo "export LD_LIBRARY_PATH=/opt/oracle/instantclient_ xxx" >> /root/.bashrc echo "export ORACLE_HOME=/opt/oracle/instantclient_ xxx" >> /root/.bashrc
- Ставим OCI в Ruby:cd ruby-oci8-2.1.5/ ruby setup.rb config ruby setup.rb setup ruby setup.rb install
Тадам! Все готово! Теперь Windows с MSF. Здесь чуть более кратко: не стоит оно того :).
Задача
Расширить атаку через Oracle-линки
Решение
Представь себе ситуацию: нашел ты SQL-инъекцию в веб-приложении или же подобрал учетку через TNS listener, то есть получил доступ к ораклу на бэкенде. Конечно, первым делом надо порыскать по доступным табличкам и слить все интересное, но потом всегда есть желание проникнуть «глубже» и добраться до ОС или других серверов, например. В общем, так называемый этап постэксплуатации. Конечно, здесь важный шаг — посмотреть привилегии пользователя и уже танцевать от них. Но мы сейчас сконцентрируемся на одном из методов — через связи (они же «db link’и»).
Может быть, тебе незнакомо такое понятие, но мы это поправим. Насколько я помню, все мощные СУБД, будь то Oracle, MS SQL, Postgres, имеют возможность сами подключаться к другим базам данных и вынимать инфу из них. Ты подключаешься в одну базу А и говоришь ей подключиться к СУБД Б, а дальше можешь посылать запросы через А в базу данных на Б. И что еще полезнее — данные можно «смешивать», то есть база данных А может выдавать различные итоги в зависимости от данных, полученных с Б.
Идейно все просто, согласись? А самое главное — полезно для нас. Но давай сконцентрируемся на Oracle и ее специфике.
И начну я с грустного. «Обычный» юзер (созданный с ролями connect и resource, как это обычно происходит) не имеет прав на создание линков. Но это справедливо для версий с 10g R2 и более поздних. В более ранних версиях привилегия на создание линка входила в роль connect. Но что, если необходимые права у нас есть? Тогда мы можем сделать многое…
Представь себе ситуацию (причем вполне типовую): есть корпоративная сеть и в ней интересующая нас критичная система. Пусть это будет ERP. Но, как это бывает в здравомыслящих компаниях, ERP располагается в специальном сетевом сегменте с приличной фильтрацией, а наружу торчит только какой-нибудь веб-портал. Печалька… Но очень часто гораздо в меньшей строгости «живут» девелоперская версия той же ERP и версия ERP для тестирования. Кстати, такие тройки: боевая версия (продакшен), предпродакшен (тестирование) и девелоперская версия ERP — типовое решение в компаниях для любых крупных систем, так как они постоянно допиливаются, да и тестировать их надо. Так вот, мы можем атаковать эти версии, за которыми меньше приглядывают, а с них уже идти в атаку на прод, через те же линки например. Да, опять-таки стандартная ситуация, когда между продакшеном и другими «копиями» действуют гораздо более свободные правила фильтрации.
Немного практики. Просмотр привилегий:
SELECT * FROM USER_SYS_PRIVS;
Просмотр ролей:
SELECT * FROM USER_ROLE_PRIVS;
Создание линка:
CREATE DATABASE LINK link_name USING @ORCL;
Здесь мы создаем линк с именем link_name к базе данных на том же хосте, с другим SID’ом — ORCL (точнее service name’ом). При этом используется тот же логин и пароль, что и у действующего юзера.
Чтобы сказать базе данных, что данные мы хотим «переслать» в линк, мы должны указывать имя после собаки. Типа @link_name. Причем линк нужно указывать у имени таблицы. Например, запрос данных с удаленного сервера:
SELECT * from table_name@link_name;
Если же надо выполнить какую-то функцию на удаленном сервере, то линк нужно писать после имени функции, но до параметров:
SELECT function_name@link_name(function,parameters) from dual;
Кроме локальных линков, ты можешь создавать и удаленные, и даже с другими кредами:
CREATE DATABASE LINK link_name CONNECT TO username IDENTIFIED BY password USING '//remote_host_name_or_ip:1521/ORCL;
Тут, думаю, ясно, что username и password — креды для подключения, а ORCL — это опять-таки service name.
И еще tip для удаления линков. Может пригодиться, чтобы подчищать хвосты.
DROP DATABASE LINK link_name;
Теперь давай прикинем, что мы можем сделать из этой возможности.
- При создании локального линка ты сразу получишь ответ — есть такой SID или нет. При удаленном линке после первого запроса по линку получаешь аналогичный ответ. Причем в случае существования SID’а проверяются логин и пароль и система также возвращает ошибку, если они неверны. Таким образом, мы можем спокойно сначала перебирать SID’ы, а потом уже стандартные или не очень учетки.
- Можно подключиться к самому же себе, но под другой учеткой! Это не так актуально для доступа через TNS, но вот для SQL-инъекций — это самое то. Приведу пример. Есть SQLi в приложении, и мы можем выполнять какие-то запросы от какого-то юзера. Но у него может не быть интересных нам прав. А потому мы берем и создаем линк в ту же базу данных, но с другими кредами (брутфорс нам поможет). И вуаля! Мы все там же — за веб-приложением, но уже имеем в базе данных гораздо больше прав. Магия практически. Но здесь есть одно обидное ограничение. Для линков нет возможности создавать привилегированные подключения (под SYSDBA), что в зависимости от версии оракла может нас сильно (или не очень) ограничить в возможностях.
- Когда ты получил доступ в базу данных — посмотри, нет ли там уже созданных линков. Шанс невелик, но все возможно. Причем, во-первых, там могут быть линки, уже созданные под твоим же юзером кем-то ранее, а бывают еще общие (PUBLIC) линки, созданные под каким-то другим пользователем, но доступные всем. Все доступные юзеру линки:select * from USER_DB_LINKS;
- Так как мы можем указывать имя хоста и порт, а также из-за информативности ошибок от базы данных мы легко можем проводить сканирование внутренней инфраструктуры. Ну ладно, не очень легко, так как небыстро, но можем :).
- После небольшого ресерча оказалось, что мы можем проводить SSRF-атаки. Да-да, куда уж без них :). К сожалению, это не любимый gopher и здесь есть ряд обидных ограничений. Во-первых, мусор в несколько строк в начале (бинарные заголовки от TNS-протокола), во-вторых, в некоторых запрещенных символах. Ну и да, ответ от сервера нам не получить. Зато мы можем делать перенос строк, а потому вполне можем общаться с различными плейнтекстовыми протоколами. FTP, SMTP… Вероятно, против memcached заработает. В указанном выше способе создания линка наши команды идут после ORCL и до закрывающей кавычки.
- И еще один «итог» SSRF — NTLM-релей. Мы можем указать линк на себя, перехватить NTLM-аутентификацию и переслать ее на другой сервер. Фичу эту я до конца не проверил, но к выходу журнала, возможно, будет готовый PoC.
Надеюсь, не забыл ничего интересного, связанного с этой темой.
Задача
Открыть замок с помощью пластиковой карточки
Решение
Разбавим немного наш раздельчик триком из полюбившегося в хакерской среде lockpicking’а. Причем сугубо полезным. Ведь с каждым такое может случиться, что дверь за тобой захлопнулась, а ключи остались за дверью.
Итак, представь себе. У нас есть: дверь, замок, пластиковая карточка, желание открыть дверь. Но главное, что нужно для успеха, — определенный вид замка. Этот тип используется повсеместно в офисах и внутри квартир, в нем язычок (треугольный или штырек внутри, который препятствует открытию) остается подвижным даже после закрытия замка. То есть ручка двери заблокирована замком и потому мы не можем подвинуть язычок для открытия двери. Но сам язычок подвижен. Ну, я думаю, ты понял.
Суть «атаки» очень проста: если язычок подвижен, то нам просто его надо подвинуть. А для того, чтобы его подвинуть, нам понадобится пластиковая карточка. Первое, что приходит на ум, — банковская карта (а-ля Visa), но рекомендуется что-то более гибкое и подвижное. Обычно это дисконтные карты всяких магазинов. И еще одна тонкость для начала: представим, что мы находимся со стороны двери со скошенной стороной язычка.
Итак, последовательность проста. Вставляем карточку в дверную щель и упираемся перпендикулярно в язычок. Давим на карточку и сильно сгибаем ее в сторону дверной ручки. И последнее: резко выворачиваем карточку в противоположную сторону (то есть к дверному косяку) и при этом нажимаем на саму дверь.
Получается, что пластиковая карточка становится рычагом, который сдвигает язычок.
Возможно, с первого раза (рывка) не получится открыть дверь, так как язычок не до конца сдвинется, а потому следует последние два шага повторить несколько раз.
Способ дельный, но есть трудности. Во-первых, если мы с той стороны двери, куда выходит нескошенная часть язычка, то дело затрудняется, так как упираться нам надо наискосок (чтобы опять-таки хоть частично упереться в скошенную поверхность).
Во-вторых, нам очень часто могут помешать либо узкие зазоры между дверью и коробкой (карточку особо не подсунешь), либо молдинги/наличники, которые закрывают нам зазор.
Задача
Проэксплуатировать SQL-инъекции под Oracle
Решение
И вот второй вопрос про Oracle. На самом деле он более крут, хотя и поменьше в размерах. Итак, представим, что у нас есть веб-приложение и в нем SQLi, а на backend’е у нас Oracle. Что мы будем делать? Ну конечно, сольем критичную инфу из базы. Неплохо, но как насчет того, чтобы углубиться подальше и добраться до ОС?
Как ни странно, Oracle — это своего рода монстр, и людей, которые в нем шарят (особенно в безопасности), совсем немного. Как итог — есть очень приличный шанс на успех в постэксплуатации из-за кривых настроек или недопатченности базы данных…
Все бы хорошо, да только нам мешает одна приличная проблема — весь самый вкусный функционал требует всяких радостей из PL/SQL (процедуры, анонимные блоки, DDL и кучу других непонятных штук), которые, в свою очередь, требуют делать множественные запросы (если честно, не знаю, как по-русски правильно сказать multi statement). А в обычной ситуации у нас нет возможности их производить. Если проще, multi statement — это несколько запросов, разделенных точкой с запятой, но их мы не можем напихать в какой-нибудь select.
Хотя на самом деле есть вариант. Некоторые функции позволяют передавать им целые блоки запросов. То есть ничто не мешает нам в скулю в select добавить такую функцию, а в нее уже напихать необходимых страшностей… Но до 2011 года все было грустно, так как была известна вроде как только одна такая функция — sys.kupp$proc.create_mater_process()
, а для использования ее требовалась роль DBA. Совсем не тру. Так вот, в 2011 году Sumit «Sid» Siddharth из 7Safe представил шикарный white paper «Hacking Oracle from Web: Part2», в котором поведал о своей отличной находке: есть еще две функции, в которые можно внедрять PL/SQL-блоки, а самое главное, которые доступны для роли Public. Этими функциями являются
dbms_xmlquery.getxml()
dbms_xmlquery.newcontext()
Таким образом, по сути, любая скуля с правами обычного юзера становилась эквивалентна прямому доступу в СУБД (как через SQL*Plus). Что еще круче, эти функции присутствуют во всех версиях Oracle после 8-й. Правда, в 12-й ее возможности почикали, но это не меняет того, что самые активно используемые версии — 10-я и 11-я — уязвимы.
Теперь давай перейдем к практике. В качестве примера создадим линк из первой задачки внутри select, куда у нас инъекция.
Запрос в БД будет select * from products where id = ‘SQLi_here’
. Тогда в скулю мы пишем следующее:
' and (select dbms_xmlquery.newcontex('declare PRAGMA AUTONOMOUS_TRANSACTION; begin execute immediate ''CREATE DATABASE LINK link_name CONNECT TO username IDENTIFIED BY password USING '''//remote_host_name_or_ip:1521/ORCL''' ''; commit; end;') from dual) is not null –-
Может показаться, что тут что-то трудное, но на деле просто.
Если отбросить все до первой и от последней скобки, что необходимо лишь для работоспособности запроса к СУБД, то мы имеем лишь select функции dbms_xmlquery.newcontex с нашим блоком запросов в скобках. Внутренность я чуть поясню.
declare PRAGMA AUTONOMOUS_TRANSACTION
— это указание компилятору оракла, что далее идет автономная транзакция. Если проще, то это значит, что ее выполнение не зависит от успешности выполнения других транзакций (например, процедуры-родителя);- Begin — указывает на начало анонимного блока, а end — на его окончание;
- execute immediate — необходимо указывать, если в анонимном блоке мы хотим использовать Data Definition Language (DDL) запросы. Это такие специальные запросы: на изменение структуры базы данных, изменение юзеров, ролей и так далее. Считай «системные»;
- commit — говорит о том, что произведенные изменения необходимо записать в базу данных (если этого не сделать, изменения останутся только в памяти).
Внутри же идет тот же пример, что и указан выше, с тем лишь изменением, что каждое следующее «вложение» необходимо «окучивать» еще одной парой одинарных кавычек. Но это уже совсем обычная фича оракла.
В примере использована функция dbms_xmlquery.newcontex, но для dbms_xmlquery.getxml все будет аналогичным, и приводить для нее пример нет смысла.
Как видишь, все просто. Руки у нас развязаны. В white paper ты найдешь несколько примеров эксплуатации различных уязвимостей, например для повышения привилегий.
Задача
Обнаружить место жительства владельца Apple-девайса
Решение
И немного о приватности. Это направление уже давно муссируется, и неспроста. Вне зависимости от того, есть ли у тебя секреты, хочется хоть как-то контролировать информацию о своей частной жизни. Но с развитием технологий все труднее это делать, она все чаще просачивается. Причем даже не для корпораций или спецслужб, а кому попало.
На самом деле данная задачка немного «притянута за уши», но она хорошо обобщает три интересные фичи. Кроме того, во многом это все актуально и для владельцев мобильных девайсов других фирм. Но перейдем к делу и конкретизируем ситуацию. Есть какой-то девайс и мы, которые находимся в относительной близости.
Всем известно, что Wi-Fi-роутеры систематически посылают широковещательные запросы в канал о том, что они есть, такие хорошие, и о своих характеристиках, необходимых для подключения к ним. Но мобильные устройства (точнее, почти все Wi-Fi-клиенты) систематически рассылают информацию в поисках известных им сетей (точнее, тех, для которых стоит автоматическое подключение). Если у человека включен Wi-Fi на устройстве, то мы чисто из эфира можем уже вынуть информацию о тех местах, которые он посещал. SSID’ы сетей зачастую несут в себе вполне осмысленную информацию. Например, названия кафе, отелей, компаний.
И здесь есть интересное последствие, на котором во многом основана работа известной тулзени — KARMA. Мы можем отснифать имя SSID’а и по-быстрому поднять такую же точку доступа, после чего атакуемый девайс сам к нам может подключиться. А может не подключиться :). Здесь все зависит от конкретной реализации ПО. Некоторые системы смотрят на изменение протокола подключения, а некоторые — нет. То есть если к домашнему роутеру ты подключаешься с ноута по WPA, например, а я подниму точку с таким же SSID’ом, но открытую, то в зависимости от ПО в твоей ОС твой ноут все равно может подключиться к моей точке.
У Apple-девайсов, насколько мне известно, есть такая проверка. Но чаще всего находится какая-то беззащитная точка из «запомненных», которую мы можем и подменить.
О’кей, мы заставили девайс подсоединиться к себе. Что дальше?
А дальше интересная особенность Apple-девайсов (ноги которой растут из какого-то RFC): при подключении к новой сети они пытаются найти предыдущие гейтвей. То есть они запрашивают — а есть ли здесь такой-то IP с таким-то MAC’ом? И данные эти берутся от предыдущих подключений.
Я протестировал на iOS 7 версии, и такой запрос действительно проскакивает сразу же после подключения устройства к сети. Но только один, хотя в теории должны быть три последние точки доступа.
Да, что это нам может дать? Не считая раскрытия внутренней IP-адресации, мы получаем MAC-адрес гейта, который с большой вероятностью является Wi-Fi-роутером. А если это так, то, вспомнив, что MAC аналогичен BSSID’у Wi-Fi-точки, мы получаем очень интересный материал для работы!
Ты, наверное, в курсе, что многие корпорации (например, Google) собирают информацию о Wi-Fi-точках и их территориальном расположении. Например, всякие Android- и Apple-девайсы делают это в фоновом режиме постоянно (насколько мне известно). Прогулялся с включенным Wi-Fi — считай, собрал инфу для корпорации. Правда, сейчас чисто за счет Wi-Fi мы можем добиться высокой точности определения месторасположения.
Но самое интересное для нас, что некоторые компании делятся этой информацией (даже бесплатно). То есть мы можем запросить у сервиса, где находится такой-то BSSID, и нам выведут его координаты. Та-дам!
Но стоит сказать, что несколько лет назад был у гугла некий скандальчик, в результате которого «пояса затянулись». Теперь одного BSSID’а не хватает, а надо их два. Хотя фактически это незначительно затрудняет задачу. Во-первых, потому как Apple-девайсы дисклозят нам несколько последних MAC’ов. Во-вторых, потому, что мы можем перебирать известные BSSID’ы точек и, играя в игру «тепло — холодно», найти интересующую нас Wi-Fi-точку.
Вот такие вот дела. Описание API от Google. А вот еще сервис, предоставляющий локацию по одному BSSID’у (но база в основном в Америке). Кроме того, знающие люди посоветовали тулзу iSniff-GPS, которая выполняет часть из описанных фич, так что присмотрись к ней, если данная тема тебя заинтересовала.
Настало время, когда, придя в кафешку с кармой и увидев симпатичную девушку, после некоторых махинаций ты будешь знать о ней, возможно, больше, чем хотелось бы :).
Спасибо за внимание и успешных познаний нового!