
This repository contains the final report and the reproducibility artifacts for:
CVE-2018-1058: Privilege Escalation in PostgreSQL through Uncontrolled Search Path
The goal is to demonstrate the search-path trust failure behind CVE-2018-1058 using a safe local Docker environment.
The demo does not reproduce the exact historical pg_dump execution path. Instead, it reproduces the same root cause described in PostgreSQL guidance: an attacker-writable schema contains a look-alike object, and another session resolves an unqualified name to that object.
.
├── report.pdf
├── docker-compose.yml
├── README.md
└── scripts/
├── init.sql
├── init_safe.sql
├── exploit.sql
├── victim_query.sql
├── verify_qualify.sql
└── fix.sql
The final report is report.pdf. It includes the written analysis and the screenshots corresponding to the expected outputs below.
No Dockerfile is required. The project uses official postgres images.
The screenshots are embedded directly in report.pdf, so they are not provided as separate image files.
Install:
psql client, optional but recommendedThe demo uses two PostgreSQL containers:
Make sure ports 15432 and 15433 are free.
The expected execution order is:
exploit.sql as attacker.victim_query.sql as victim and observe the CVE-2018-1058 DEMO: prefix.verify_qualify.sql as victim and observe normal lowercase output.fix.sql as postgres.victim_query.sql and observe normal lowercase output.exploit.sql on port 15433 and observe permission denied for schema public.docker compose up -d pg_vulnerable
docker compose ps
Expected result: service pg_vulnerable should be running and mapped to port 15432.
Check the PostgreSQL version:
docker exec -it cve1058_pg_vulnerable psql -U postgres -d demo_cve1058 -c "SELECT version();"
Expected result: PostgreSQL 10.2.
docker exec -it cve1058_pg_vulnerable psql -U postgres -d demo_cve1058 -c "\du"
Expected roles:
postgresattackervictimThe attacker is not a PostgreSQL superuser.
Run the attacker script:
PGPASSWORD='AttackerPw!ChangeMe' \
psql -h 127.0.0.1 -p 15432 -U attacker -d demo_cve1058 \
-v ON_ERROR_STOP=1 -f scripts/exploit.sql
Expected output:
CREATE TABLE
GRANT
GRANT
CREATE FUNCTION
This creates:
public.exploit_log table;public.lower(varchar) function.PGPASSWORD='VictimPw!ChangeMe' \
psql -h 127.0.0.1 -p 15432 -U victim -d demo_cve1058 \
-v ON_ERROR_STOP=1 -f scripts/victim_query.sql
Expected output:
CVE-2018-1058 DEMO: Alice Demo
CVE-2018-1058 DEMO: Bob Demo
This shows that the victim's normal query resolved lower(...) to the attacker-controlled function.
PGPASSWORD='AttackerPw!ChangeMe' \
psql -h 127.0.0.1 -p 15432 -U attacker -d demo_cve1058 \
-c "TABLE public.exploit_log;"
Expected result: at least two rows in public.exploit_log, one for each row processed by the victim query.
PGPASSWORD='VictimPw!ChangeMe' \
psql -h 127.0.0.1 -p 15432 -U victim -d demo_cve1058 \
-v ON_ERROR_STOP=1 -f scripts/verify_qualify.sql
Expected output:
alice demo
bob demo
This works because pg_catalog.lower(...) forces PostgreSQL to use the built-in function.
PGPASSWORD='postgres' \
psql -h 127.0.0.1 -p 15432 -U postgres -d demo_cve1058 \
-v ON_ERROR_STOP=1 -f scripts/fix.sql
Expected output may include:
DROP FUNCTION
DROP TABLE
REVOKE
REVOKE
Then rerun the victim query:
PGPASSWORD='VictimPw!ChangeMe' \
psql -h 127.0.0.1 -p 15432 -U victim -d demo_cve1058 \
-v ON_ERROR_STOP=1 -f scripts/victim_query.sql
Expected output:
alice demo
bob demo
The attacker-controlled function is gone, and the query returns normal lowercase strings.
docker compose up -d pg_fixed
docker compose ps
Check the version:
docker exec -it cve1058_pg_fixed psql -U postgres -d demo_cve1058 -c "SELECT version();"
Expected result: PostgreSQL 10.3.
PGPASSWORD='AttackerPw!ChangeMe' \
psql -h 127.0.0.1 -p 15433 -U attacker -d demo_cve1058 \
-v ON_ERROR_STOP=1 -f scripts/exploit.sql
Expected output:
ERROR: permission denied for schema public
This means the attacker cannot create the fake function in public, so the attack chain stops before name resolution.
To stop the containers:
docker compose down
To remove volumes and reset the project completely:
docker compose down -v
This demo is intentionally harmless. It does not steal data, access files, or execute operating-system commands.
The exploit uses a visible string prefix and a log table to prove that PostgreSQL resolved an unqualified function name to an attacker-controlled object.
The official CVE concerns pg_dump and other client applications. This repository demonstrates the same search-path trust failure in a safe and reproducible classroom setting.
If a port is already in use, stop any local PostgreSQL service or change the host ports in docker-compose.yml.
If the output does not match the expected results, reset the environment with:
docker compose down -v
docker compose up -d pg_vulnerable
If psql is not installed locally, the version and role inspection commands can still be run with docker exec inside the containers.
If the exploit fails on pg_vulnerable, make sure the database was reset and that scripts/exploit.sql is being executed before scripts/fix.sql.
| Service | Version | Container name | Host port | Purpose |
|---|
pg_vulnerable | PostgreSQL 10.2 | cve1058_pg_vulnerable | 15432 | vulnerable demonstration |
pg_fixed | PostgreSQL 10.3 | cve1058_pg_fixed | 15433 | patched/hardened comparison |