14.03.2015

Дешифровка паролей к учетным записям в MSSQL

image

Некоторое время назад я написал статью о дешифровке паролей для связанных серверов . Используя ту же самую технику, возможна дешифровка паролей учетных записей SQL-сервера. Я немного модифицировал предыдущий скрипт, предназначенный для расшифровки паролей, а именно поменял местонахождение зашифрованных паролей. В итоге получился обновленный Powershell-скрипт для расшифровки паролей учетных записей.

Автор: Antti Rantasaari

Некоторое время назад я написал статью о дешифровке паролей для связанных серверов (https://blog.netspi.com/decrypting-mssql-database-link-server-passwords/). Используя ту же самую технику, возможна дешифровка паролей учетных записей SQL-сервера. Я немного модифицировал предыдущий скрипт, предназначенный для расшифровки паролей, а именно поменял местонахождение зашифрованных паролей. В итоге получился обновленный Powershell-скрипт для расшифровки паролей учетных записей.

Замечания те же самые, что и при расшифровке паролей для связанных серверов. Плохая новость в том, что для дешифровки требуются привилегии сисадмина (sysadmin) SQL-сервера и локального администратора Windows-сервера. С другой стороны, если злоумышленник обладает правами администратора, то потенциально сможет расшифровать большинство сохраненных паролей. Так что не следует хранить бесхозные учетные записи в базе данных, и не наделять ненужными правами те учетные записи, которые используются для доступа к внешним ресурсам.

Учетные записи SQL-сервера

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

Простой пример – использование учетной записи прокси-сервера. Во время запуска xp_cmdshell по умолчанию используются права служебной учетной записи SQL-сервера (SQL Server service account). Однако учетную запись прокси-сервера можно сконфигурировать так, что сохраненная процедура xp_cmdshell использовала менее привилегированный аккаунт операционной системы, а не служебную учетную запись, часто наделенную расширенными полномочиями.

Когда учетные записи сохраняются в базу SQL-сервера, пароли шифруются при помощи обратимого алгоритма шифрования (чтобы не возникало никаких проблем при использовании этих аккаунтов). Следовательно, становится возможным расшифровка паролей, чему, собственно, и посвящена данная статья.

Где хранятся пароли

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

SELECT object_definition(OBJECT_ID('sys.credentials'))

Компания Microsoft дает довольно размытое описание таблицы master.sys.sysobjvalues: «Таблица есть в каждой базе данных и хранит значения общих свойств для каждой записи. На каждое свойство предусмотрена отдельная строка таблицы». Таблица master.sys.sysobjvalues содержит огромное количество информации. У свойств, имеющих отношение к учетным записям, в колонке valueclass находится значение 28. Зашифрованные пароли хранятся в колонке imageval с valclass=28 и valnum=2.

Рисунок 1: Строки, имеющие отношение к зашифрованным учетным записям

К таблице master.sys.sysobjvalues можно получить доступ только при помощи выделенного административного соединения (Dedicated Administrative Connection, DAC) (более подробно про DAC написано в http://technet.microsoft.com/en-us/library/ms178068%28v=sql.105%29.aspx).

Алгоритм шифрования в MSSQL

Основные моменты, касающиеся шифрования в MSSQL, описаны в статье https://blog.netspi.com/decrypting-mssql-database-link-server-passwords/. В двух словах: пароли шифруются при помощи главного ключа службы (Service Master Key, SMK), который можно получить, используя DPAPI (Data Protection Application Programming Interface).

Расшифровка паролей

В зависимости от версии MSSQL-сервера пароли шифруются при помощи алгоритма AES (MSSQL 2012+) или 3DES (MSSQL 2008 и более ранние версии). Пароли, хранящиеся в таблице sys.sysobjvalues в колонке imageval, перед дешифровкой должны быть слегка обработаны (тем же самым способом, что пароли связных серверов). После парсинга пароли можно расшифровать при помощи SMK.

Расшифровка паролей при помощи powershell-скрипта

Немного модифицированная версия «Get-MSSQLLinkPasswords.psm1» с предсказуемым именем «Get-MSSQLCredentialPasswords.psm1» автоматизирует расшифровку паролей. Скрипт находится здесь https://github.com/NetSPI/Powershell-Modules/blob/master/Get-MSSQLCredentialPasswords.psm1

Скрипт должен быть запущен локально на MSSQL-сервере (поскольку DPAPI требует доступа к локальному машинному ключу). Пользователь, запускающий скрипт, должен иметь привилегии администратора (sysadmin) ко всем экземплярам базы данных (требуется для DAC-соединения) и локального администратора Windows-сервера (для доступа к байтам с энтропией в реестре). Кроме того, если включен контроль учетных записей пользователя (User Account Control, UAC), скрипт должен быть запущен от имени администратора.

Ниже показан алгоритм работы скрипта.

1. Идентификация всех экземпляров MSSQL на сервере.

2. Создание DAC-соединения к каждому экземпляру.

3. Выборка зашифрованных паролей из таблицы master.sys.sysobjvalues (колонка imageval) для каждого экземпляра.

4. Получение главного ключа службы (Service Master Key, SMK) из таблицы master.sys.key_encryptions (строки со значениями key_id равным 102). Получение версии SQL-сервера, зашифрованной как LocalMachine, на основе колонки thumbprint.

5. Извлечение значения энтропии из реестра по адресу HKLM:\\SOFTWARE\Microsoft\Microsoft SQL Server\[instancename]\Security\Entropy.

6. Использование полученной информации для дешифровки SMK.

7. Определение алгоритма шифрования (AES или 3DES), который использовался для шифрования SMK, на основе версии SQL-сервера и длины SMK-ключа.

8. Дешифровка паролей при помощи SMK.

9. В случае успеха скрипт отображает расшифрованные пароли.

Пример работы скрипта:

PS C:\> Get-MSSQLCredentialPasswords | out-gridview

Рисунок 2: Результат работы скрипта

Скрипт был протестирован на MSSQL 2008 и 2012.