MSSQL Injection
Last updated
Was this helpful?
Last updated
Was this helpful?
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:
(From ) 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()
:
fn_xe_file_target_read_file()
example:
Permissions: Requires VIEW SERVER STATE permission on the server.
fn_get_audit_file()
example:
Permissions: Requires the CONTROL SERVER permission.
fn_trace_gettable()
example:
Permissions: Requires the CONTROL SERVER permission.
One technique that keeps coming up is the usage of the undocumented stored procedure xp_dirtree
that allows you to list the directories in a folder. This stored procedure supports UNC paths, which can be abused to leak Windows credentials over the network or extract data using DNS requests.
If you are able to execute operating system commands, then you could invoke Powershell to make a curl (Invoke-WebRequest
) request. You could do this via the hacker favorite xp_cmdshell
as well.
Alternatively, you could also use a User Defined Function in MSSQL to load a DLL and use the dll to make the request from inside MSSQL directly.
Let’s look at the above techniques in a little more detail.
Essentially,
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.
xp_cmdshell
is disabled by default. You can enable it using the SQL Server Configuration Option. Here’s how
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.
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.
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;
)
Once the assembly is added and the function created, we can run the following to make our HTTP requests
The query to retrieve the schema, tables and columns from the current database:
Error-based vectors need an alias or a name, since the output of expressions without either cannot be formatted as JSON.
Error-based vector:
Permissions: The BULK option requires the ADMINISTER BULK OPERATIONS or the ADMINISTER DATABASE BULK OPERATIONS permission.
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.
Scientific (0e) and hex (0x) notation for obfuscating UNION:
A period instead of a whitespace between FROM and a column name:
\N seperator between SELECT and a throwaway column:
Information taken from ****
****.
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 . This method has been used in of posts on the Internet.
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, .
There are other stored procedures etc. as well that can be used for similar results.
The extended stored procedure . This command is run as the SQL Server service account.
You could use something like , download the Windows port of netcat/ncat, , or simply invoke Powershell’s Invoke-WebRequest
to make HTTP requests to perform Server Side queries.
to load the binary into MSSQL as a CLR assembly and then invoke HTTP GET requests from within MSSQL.
The as specified
(From ) 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.
(From ) An example of retrieving a local file C:\Windows\win.ini
using the function OpenRowset():
(From ) The current SQL query being executed can be retrieved from access sys.dm_exec_requests
and sys.dm_exec_sql_text
:
(From ) Non-standard whitespace characters: %C2%85 или %C2%A0: