
Snipe-IT PoC exploit for CVE-2025-59712 and CVE-2025-59713
Dieses PoC stellt ein automatisiertes Skript zur Verfügung, um CVE-2025-59712 (XSS im User-Agent-Header) und CVE-2025-59713 (unsichere Deserialisierung) auszunutzen.
Diese beiden Sicherheitslücken wurden von Synacktiv im Rahmen einer Sicherheitsforschung an der Snipe-IT-Software entdeckt. Snipe-IT ist ein Open-Source-Asset-Management-System, das auf Laravel basiert und Organisationen dabei helfen soll, ihre physischen und digitalen Assets zu verfolgen und zu verwalten.
Eine technische Beschreibung findet sich im entsprechenden Security Advisory auf der Synacktiv-Website.
Dieses Skript bietet drei Unterbefehle, die den Ausnutzungsmodi entsprechen: xss, rce und fullchain.
Dieser Unterbefehl nutzt CVE-2025-59712 aus, der es einem Benutzer mit niedrigen Berechtigungen erlaubt, beliebiges JavaScript in die HTML-Seite einzuschleusen, die beim Aufruf der Route /reports/activity gerendert wird. Dies kann nur von einem Administrator oder einem Benutzer mit expliziten Ansichtsberechtigungen für Berichte durchgeführt werden. Die Injektion ist aufgrund einer unzureichenden Bereinigung des User-Agent-Feldes möglich, wenn ein Benutzer seine Profilinformationen aktualisiert.
Dazu wird es sich zunächst als Benutzer mit niedrigen Berechtigungen anmelden und dann den JavaScript-Code injizieren, der in der über das --javascript-Flag angegebenen Datei definiert ist.
$ python3 exploit.py xss --help
Usage: exploit.py xss [OPTIONS]
Execute XSS attack only with custom JavaScript payload
╭─ Options ────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮
│ * --url -u TEXT Target Snipe-IT URL [required] │
│ * --login -l TEXT Low-privileged username [required] │
│ * --password -p TEXT Low-privileged password [required] │
│ * --new-name -n TEXT New name for low-privileged user [required] │
│ * --javascript -js TEXT Path to custom JavaScript file [required] │
│ --proxy -x TEXT HTTP proxy (http://ip:port) │
│ --verbose -v [quiet|normal|verbose] Logging verbosity [default: normal] │
│ --help Show this message and exit. │
╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯
[!IMPORTANT]
Während der Sicherheitsforschung wurden Tests mit einer Version von Snipe-IT durchgeführt, die standardmäßig dasUser-Agent-Feld anzeigte, in das das schädliche JavaScript injiziert wird. Seit dem Commit 10e5d88 wird dieUser-Agent-Eigenschaft standardmäßig nicht mehr angezeigt, wenn die Aktionsprotokolltabelle gerendert wird. Der Administrator, der die XSS auslöst, muss daher in den Ansichtsoptionen für Snipe-IT-Versionen nach diesem Commit das KontrollkästchenUser-Agentaktiviert haben.
Dieser Unterbefehl nutzt CVE-2025-59713 aus, der eine Remote-Code-Ausführung ermöglicht, wenn die Anmeldedaten eines Administrators oder Superadministrators bekannt sind. Dazu werden die folgenden Schritte ausgeführt:
db-dumps/mysql-snipeit.sql, die ein neues benutzerdefiniertes Feld erstellen und das letzte Aktionsprotokoll mit einem JSON-Objekt bearbeiten, das bei der Wiederherstellung die Laravel-Pop-Kette enthält.[!TIP] Standardmäßig enthält Snipe-IT die
.env-Datei im Backup. Wenn das Skript sie erkennt, wird derAPP_KEY-Wert angezeigt und die.env-Datei im Verzeichnis./outputgespeichert (ein benutzerdefinierter Speicherort für diese Datei kann mit--output-dirangegeben werden).
[!CAUTION] Das Wiederherstellen eines Backups trennt alle mit der Instanz verbundenen Benutzer.
/api/v1/reports/activity aufgerufen, was die Deserialisierung auslöst und die Laravel-Pop-Kette ausführt.$ python3 exploit.py rce --help
Usage: exploit.py rce [OPTIONS]
Execute RCE attack only (requires existing admin account)
╭─ Options ────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮
│ * --url -u TEXT Target Snipe-IT URL [required] │
│ * --admin-user -au TEXT Admin username [required] │
│ * --admin-pass -ap TEXT Admin password [required] │
│ --output-dir -od PATH Output dir for .env file [default: /home/ninja/Téléchargements/snipe-it-advisory/exploit/output] │
│ --shell-ip -si TEXT Reverse shell IP address │
│ --shell-port -sp INTEGER Reverse shell port │
│ --command -c TEXT Custom command (overrides reverse shell) │
│ --proxy -x TEXT HTTP proxy (http://ip:port) │
│ --verbose -v [quiet|normal|verbose] Logging verbosity [default: normal] │
│ --help Show this message and exit. │
╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯
Der Unterbefehl fullchain zielt darauf ab, beide Sicherheitslücken (XSS und RCE) miteinander zu verketten. Er entspricht einem Szenario, in dem Sie nur Zugriff auf einen Benutzer mit niedrigen Berechtigungen haben und eine Remote-Code-Ausführung erreichen möchten. Dies funktioniert nur, wenn der Benutzer, der die Seite /reports/activity besucht, ein Administrator oder Superadministrator ist. Tatsächlich haben nur diese Rollen die Rechte, ein Backup zu erstellen und wiederherzustellen, was notwendig ist, um die Datenbank zu vergiften und später die Laravel-Pop-Kette auszulösen.
Dazu wird das Skript:
--command-Flag anpassen, wie beim RCE-Modus).User-Agent-Feldes mit einem <scr>-Tag, um den Browser des Opfers zu zwingen, die schädliche JavaScript-Vorlage zu laden./reports/activity besucht, wird die XSS ausgelöst und das schädliche JavaScript wird geladen und vom Browser des Opfers ausgeführt. Ab diesem Zeitpunkt werden die gleichen Schritte wie im RCE-Modul ausgeführt, jedoch in JavaScript.Dieser Modus verwendet mehrere zusätzliche JavaScript-Bibliotheken, alle Credits gehen an ihre jeweiligen Autoren:
$ python3 exploit.py fullchain --help
Usage: exploit.py fullchain [OPTIONS]
Execute full attack chain: XSS -> Backup manipulation -> RCE
╭─ Options ────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮
│ * --url -u TEXT Target Snipe-IT URL [required] │
│ * --login -l TEXT Low-privileged user's username [required] │
│ * --password -p TEXT Low-privileged user's password [required] │
│ * --new-name -n TEXT New name for low-privileged user [required] │
│ --ip -i TEXT HTTP server IP address (default: auto-detect) │
│ * --port -P INTEGER HTTP server port [required] │
│ --admin-user -au TEXT Admin username to create [default: admin_rce] │
│ --admin-pass -ap TEXT Admin password to create [default: password123] │
│ --shell-ip -si TEXT Reverse shell IP address │
│ --shell-port -sp INTEGER Reverse shell port │
│ --command -c TEXT Custom command (overrides reverse shell) │
│ --proxy -x TEXT HTTP proxy (http://ip:port) │
│ --verbose -v [quiet|normal|verbose] Logging verbosity [default: normal] │
│ --help Show this message and exit. │
╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯
Um dieses Skript auszuführen, führen Sie die folgenden Befehle aus:
$ git clone https://github.com/synacktiv/CVE-2025-59712_CVE-2025-59713
$ cd CVE-2025-59712_CVE-2025-59713
$ python3 -m venv .venv && source .venv/bin/activate
$ python3 -m pip install -r requirements.txt
Es wird ebenfalls ein Dockerfile bereitgestellt, um das Skript auszuprobieren und die Ausnutzung der Sicherheitslücke nachzustellen. Es lädt eine anfällige Version von Snipe-IT, konfiguriert die Datenbank mit php artisan und richtet zwei Benutzer ein:
admin mit dem Standardpasswort AdminPassword123!lowpriv mit dem Standardpasswort LowPrivUser123!Vor dem Ausführen des Containers müssen die Dateien .env und snipe-it.conf mit der URL der Snipe-IT-Instanz aktualisiert werden:
$ sed -i 's|^APP_URL=.*|APP_URL=http://<IP>:<PORT>|' .env
$ sed -i 's|\(ServerName\s*\).*|\1http://<IP>:<PORT>|' snipe-it.conf
Der Container kann dann wie folgt ausgeführt werden:
$ docker build . -t "snipe-it-cve"
$ docker run -p 80:80 --name "snipe-it-debian" snipe-it-cve:latest