
Snipe-IT PoC exploit for CVE-2025-59712 and CVE-2025-59713
This PoC provides an automated script to exploit CVE-2025-59712 (XSS in User-Agent header) and CVE-2025-59713 (unsafe deserialization).
These two vulnerabilities were discovered by Synacktiv during vulnerability research on the Snipe-IT software. Snipe-IT is an open-source asset management system based on Laravel and designed to help organizations track and manage their physical and digital assets.
A technical writeup can be found in the dedicated security advisory on Synacktiv's website.
This script provides three subcommands, corresponding to exploitation modes: xss, rce and fullchain.
This subcommand exploits CVE-2025-59712, which allows a low-privileged user to inject arbitrary JavaScript in the HTML page rendered when calling the /reports/activity route. This can only be done by an admin user, or a user that has explicit view permissions for reports. The injection is possible due to unproper sanitization of the User-Agent field when a user updates their profile information.
To do so, it will first log in as the low-privileged user, and then inject the JavaScript code defined in the file supplied via the --javascript flag.
$ 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]
During the security research, tests were carried out on a version of Snipe-IT that, by default, displayed theUser-Agentfield in which the malicious JavaScript is injected. Since commit 10e5d88, theUser-Agentproperty is not displayed by default when the action log table is rendered. The admin that will trigger the XSS needs therefore to have ticked theUser-Agentbox in the view options for Snipe-IT versions ulterior to this commit.
This subcommand exploits CVE-2025-59713, which allows for remote code execution when credentials for an admin or superadmin user are known. To do so, the following steps are performed:
db-dumps/mysql-snipeit.sql file, which creates a new custom field and edits the last action log with a JSON object containing the Laravel pop chain upon restore.[!TIP] By default, Snipe-IT includes the
.envfile in the backup. If the script detects it, theAPP_KEYvalue is displayed and the.envfile is saved in the./outputdirectory (a custom location for that file can be specified with--output-dir).
[!CAUTION] Restoring a backup disconnects all the users connected to the instance.
/api/v1/reports/activity route is called, which triggers the deserialization and executes the Laravel pop chain.$ 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. │
╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯