发布于11小时前11小时 漏洞背景CVE-2021-41773 是 Apache HTTP Server 2.4.49 中的路径规范化缺陷。攻击者可利用编码后的点号绕过路径校验,在特定 Alias 或 ScriptAlias 配置下访问站点目录之外的文件。如果服务器同时启用了 CGI,且目标目录权限配置不当,风险可能进一步扩大到远程命令执行。Apache 2.4.50 对该问题的修复不完整,随后分配了 CVE-2021-42013。因此不能只升级到 2.4.50,历史修复基线至少应为 2.4.51,实际处置时应直接升级到当前受支持的稳定版本。以下验证仅适用于自建实验环境或已获得明确授权的目标。验证以读取容器内无敏感内容的 /etc/hostname 为止,不执行系统命令,不写入文件。影响条件Apache HTTP Server 版本为 2.4.49;2.4.50 还需检查 CVE-2021-42013。配置中存在 Alias、ScriptAlias 或其他可从 URL 映射到文件系统目录的规则。映射目录配置了 Require all granted,允许外部请求进入。若同时加载 mod_cgi 或 mod_cgid,并允许执行 CGI,漏洞影响可能从文件读取扩大为命令执行。发行版可能对 Apache 包进行安全补丁回移,不能只根据版本字符串下结论,应同时检查软件包变更记录。技术分析Apache 2.4.49 调整了 URL 路径规范化逻辑。服务器在处理点号段和百分号编码时顺序不严谨,类似 .%2e 的路径片段在部分处理阶段没有被识别为上级目录,后续解码后却会形成 ..。当请求命中 ScriptAlias 等映射规则时,路径可能逃逸到映射目录之外。是否能够读取文件,取决于 Apache 目录授权规则。默认拒绝根目录访问的配置可以降低影响;如果管理员为了处理 403 错误而对较大目录设置 Require all granted,则会直接扩大漏洞暴露面。CGI 风险需要额外条件:服务器加载了 cgi_module 或 cgid_module、映射目录允许 CGI,并且穿越后的可执行文件能够被 CGI 处理。排查时应将“文件读取条件”和“CGI 执行条件”分开判断,不应通过执行命令来确认。实验环境与非破坏性验证可使用官方历史镜像在本机回环地址搭建临时环境。端口仅绑定到 127.0.0.1,避免将存在漏洞的容器暴露到局域网或公网。docker run --rm --name apache-24149-lab \ -p 127.0.0.1:8080:80 \ httpd:2.4.49 # 查看容器版本 docker exec apache-24149-lab httpd -v # 仅验证容器内的主机名文件 curl --path-as-is -i \ ' 默认可能自行清理 URL 中的点号段,因此需要使用 --path-as-is 保留原始请求路径。若响应状态为 200,且正文与容器内 /etc/hostname 一致,即可证明存在越界文件读取。docker exec apache-24149-lab cat /etc/hostname状态码不能单独作为结论:403 通常表示目录授权规则阻断了访问;404 可能表示 Alias 路径、容器目录层级或前置代理改变了请求;400 可能来自反向代理、WAF 或 URI 校验模块。验证时应同时检查 Apache 访问日志和错误日志。生产环境问题定位首先确认 Apache 实际运行版本、加载模块及最终生效配置。不同发行版的命令名可能是 httpd 或 apache2ctl。# RHEL、Rocky Linux、容器镜像常用 httpd -v httpd -M | grep -E 'alias|cgi|cgid' httpd -t -D DUMP_RUN_CFG # Debian、Ubuntu 常用 apache2ctl -v apache2ctl -M | grep -E 'alias|cgi|cgid' apache2ctl -t -D DUMP_RUN_CFG # 搜索高风险映射和目录授权配置 grep -RInE 'ScriptAlias|Alias|Require[[:space:]]+all[[:space:]]+granted|ExecCGI' \ /etc/httpd /etc/apache2 /usr/local/apache2/conf 2>/dev/null审计配置时重点确认以下组合:ScriptAlias 指向哪个真实目录,该目录是否确有业务用途。对应 Directory 段是否设置 Require all granted。Options 是否包含 ExecCGI。是否加载 mod_cgi 或 mod_cgid。根目录是否保持 Require all denied。反向代理与后端 Apache 是否进行了不同次数的 URL 解码。若系统使用发行版回移补丁,应检查软件包变更记录,避免将已经修复的定制包误判为漏洞版本。# RPM 系发行版 rpm -q httpd rpm -q --changelog httpd | grep -E 'CVE-2021-41773|CVE-2021-42013' # Debian 系发行版 apt-cache policy apache2 zgrep -E 'CVE-2021-41773|CVE-2021-42013' \ /usr/share/doc/apache2/changelog.Debian.gz 2>/dev/null日志留痕排查Apache 默认组合日志中的请求行通常会保留客户端提交的编码路径,可搜索 %2e、%252e 以及混合编码形式。应同时检查前置负载均衡、WAF、CDN 和后端 Apache 日志,因为某一层可能已经完成解码或规范化。# Apache 常见日志位置 LOGS='/var/log/httpd/access_log /var/log/apache2/access.log /usr/local/apache2/logs/access_log' grep -EHi '(%2e|%252e|\.%2e|%2e\.)' $LOGS 2>/dev/null # 进一步关注 cgi-bin 请求及成功、部分内容响应 grep -EHi 'cgi-bin.*(%2e|%252e)' $LOGS 2>/dev/null \ | grep -E '" (200|206|500) ' # 检查同一时间段错误日志 grep -EHi 'AH00127|AH00036|Permission denied|script not found' \ /var/log/httpd/error_log \ /var/log/apache2/error.log \ /usr/local/apache2/logs/error_log 2>/dev/null日志中出现编码点号并不等同于已经成功利用。研判时需要关联响应状态、响应字节数、来源地址、User-Agent、同一会话的后续请求以及主机侧进程记录。如果服务器启用了 CGI,还应检查 Web 服务账户是否启动过异常 shell、下载工具或解释器。# 在 systemd 日志中检查 Apache 子进程相关异常 journalctl --since '24 hours ago' \ | grep -Ei 'apache|httpd|www-data|curl|wget|/bin/sh|python|perl' # 查看 Web 服务账户当前进程 ps -eo user,pid,ppid,lstart,args \ | grep -E '^(apache|www-data|httpd)[[:space:]]'若发现疑似成功读取或 CGI 执行,应先保全 access log、error log、systemd journal、反向代理日志及主机审计日志,再进行隔离和升级。不要在保全前直接清理文件或重启所有服务,否则可能破坏时间线。修复与加固首选措施是升级 Apache。2.4.51 是该漏洞链的历史最低修复版本,但已经不应作为新部署目标,应升级到厂商当前维护版本,并确认包内包含 CVE-2021-41773 和 CVE-2021-42013 的修复。对于不使用 CGI 的站点,应删除 ScriptAlias,禁用相关模块,并保持文件系统根目录默认拒绝。以下配置可作为收敛权限的参考,路径需根据实际环境调整。<Directory "/"> AllowOverride None Require all denied </Directory> # 不使用 CGI 时直接拒绝该目录 <Directory "/usr/local/apache2/cgi-bin"> Options None AllowOverride None Require all denied </Directory>如果业务必须使用 CGI,应仅对确定的 CGI 目录开放访问,不要对 /、/usr、/var 或整个站点父目录配置 Require all granted;同时限制可执行脚本类型、文件属主和写权限,避免 Web 服务账户修改 CGI 文件。# 修改后先进行语法检查 httpd -t 2>/dev/null || apache2ctl configtest # 检查通过后再平滑加载 systemctl reload httpd 2>/dev/null || systemctl reload apache2WAF 或反向代理拦截编码点号只能作为临时缓解。多层代理可能发生重复解码,简单匹配 %2e 容易被大小写、双重编码或规范化差异绕过,也可能误伤正常请求。最终仍需完成版本升级和目录授权修正。修复复核确认运行进程已经加载新版本,而不是只完成软件包安装。重新执行非破坏性请求,预期返回 400、403 或 404,且不得返回目标文件内容。确认根目录保持 Require all denied。确认无业务用途的 cgi_module、cgid_module、ScriptAlias 和 ExecCGI 已移除。持续监控编码点号请求,并对历史日志进行同源地址和时间线关联。若曾观察到成功响应或异常子进程,按已入侵事件处理,轮换主机及应用凭据,不能只修补 Apache 后结束处置。总结CVE-2021-41773 的关键不只是版本号,而是路径规范化缺陷、Alias 映射和目录授权规则共同形成的权限边界突破。验证时应控制在文件读取层面,通过版本、配置、日志和响应内容交叉确认;修复则需要同时完成版本升级、CGI 暴露面收敛、目录默认拒绝以及历史日志排查。 服务器、云资产与权限边界梳理示意 代码审计、调用链与关键函数定位示意
10小时前10小时 这个漏洞排查时要注意两个容易遗漏的点:CVE-2021-41773 只影响 2.4.49,但 2.4.50 的修复可被绕过,对应 CVE-2021-42013。因此不要把升级到 2.4.50 当成已修复,建议直接使用发行版已回补补丁的包,或升级到 2.4.51 及以上版本。 先确认实际运行版本和发行版补丁状态,不能只看响应头: apachectl -v httpd -v 2>/dev/null apache2ctl -V 2>/dev/null # Debian/Ubuntu dpkg -l 'apache2*' apt changelog apache2 | grep -E 'CVE-2021-(41773|42013)' # RHEL/CentOS/Rocky rpm -q httpd rpm -q --changelog httpd | grep -E 'CVE-2021-(41773|42013)' 在授权环境中可以做一次无副作用验证。关键是使用 --path-as-is,否则 curl 可能先规范化路径,造成误判: curl -i --path-as-is \ ' 如果返回了主机文件内容,说明路径穿越成立;返回 403/404 只能说明这条路径未成功,还要结合 Alias、ScriptAlias 和目录权限判断。建议只验证文件读取,不要在生产环境测试 CGI 命令执行。 配置侧重点检查别名目录是否被宽泛放行: apachectl -t apachectl -S apachectl -M | grep -E 'cgi|cgid' grep -RniE 'Alias|ScriptAlias|Require all granted|Options.*ExecCGI' \ /etc/apache2 /etc/httpd 2>/dev/null 根目录应默认拒绝,只对确实需要发布的目录单独授权;不需要 CGI 时应直接关闭: <Directory /> AllowOverride None Require all denied </Directory> <Directory "/var/www/html"> Options -Indexes -ExecCGI AllowOverride None Require all granted </Directory> # 不使用 CGI 时移除或禁用相关配置 # a2dismod cgi cgid # a2disconf serve-cgi-bin 日志排查不要只搜明文 ../,攻击请求通常使用编码或双重编码。可以先做粗筛: zgrep -Eai '(\.%2e|%2e\.|%2e%2e|%252e|%%32%65|cgi-bin.*(%2e|%25)|/etc/(passwd|hosts)|/proc/self)' \ /var/log/apache2/access.log* /var/log/httpd/access_log* 2>/dev/null zgrep -Eai '(AH[0-9]+|cgi|premature end of script|permission denied|client denied)' \ /var/log/apache2/error.log* /var/log/httpd/error_log* 2>/dev/null 还应关联同一来源 IP 在相近时间内的 POST 请求、异常 200 响应和响应字节数。若启用了反向代理或 CDN,需要同步检查上游原始请求日志,因为部分代理会解码或规范化 URI,Apache 日志里未必保留最初形式。 发现成功读取或疑似 CGI 执行后,不建议只升级完就结束:先隔离主机,保留 access/error 日志和进程信息,检查 Web 服务账户产生的子进程、临时目录及持久化痕迹: ps -ef --forest ss -plant find /tmp /var/tmp /dev/shm -xdev -type f -mtime -7 -ls find /var/www -type f -mtime -7 -ls journalctl -u apache2 --since '7 days ago' journalctl -u httpd --since '7 days ago' 最后重启并复测,确保旧进程已退出: apachectl -t && systemctl restart apache2 # 或 apachectl -t && systemctl restart httpd
创建帐户或登录后发表意见