MSSQL Injection
Last updated
Last updated
Learn & practice AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE) Learn & practice GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)
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:
Error-based SQL injections typically resemble constructions such as +AND+1=@@version--
and variants based on the «OR» operator. Queries containing such expressions are usually blocked by WAFs. As a bypass, concatenate a string using the %2b character with the result of specific function calls that trigger a data type conversion error on sought-after data.
Some examples of such functions:
SUSER_NAME()
USER_NAME()
PERMISSIONS()
DB_NAME()
FILE_NAME()
TYPE_NAME()
COL_NAME()
Example use of function USER_NAME()
:
These SSRF tricks were taken from here
fn_xe_file_target_read_file
It requires VIEW SERVER STATE
permission on the server.
fn_get_audit_file
It requires the CONTROL SERVER
permission.
fn_trace_gettabe
It requires the CONTROL SERVER
permission.
xp_dirtree
, xp_fileexists
, xp_subdirs
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 and posts.
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:
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.
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:
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 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:
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;
):
After successfully adding the assembly and creating the function, the following SQL code can be utilized to perform HTTP requests:
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:
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:
To check if you have the VIEW SERVER STATE permission, the following query can be used:
Non-standard whitespace characters: %C2%85 или %C2%A0:
Scientific (0e) and hex (0x) notation for obfuscating UNION:
A period instead of a whitespace between FROM and a column name:
\N separator between SELECT and a throwaway column:
According to this blog post it's possible to stack queries in MSSQL without using ";":
So for example, multiple queries such as:
Can be reduced to:
Therefore it could be possible to bypass different WAFs that doesn't consider this form of stacking queries. For example:
Learn & practice AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE) Learn & practice GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)