用友U8+渠道管理(高级版) gettoken_new SQL注入漏洞


漏洞简介

用友U8+是用友公司推出的企业管理软件平台,广泛应用于财务、供应链及人力资源等核心业务流程中。在U8+渠道管理(高级版)模块中,gettoken_new 接口存在SQL注入漏洞。该漏洞是由于页面在处理用户输入的参数时,未对输入内容进行充分过滤与安全校验,攻击者可构造恶意SQL语句,通过HTTP请求注入至后端数据库查询中。

影响版本

V18, V16.5, V16.1, V16.0, V15.1, V15.0, V13

fofa语法

title="渠道管理(高级版)"

漏洞分析

根据web.xml对url /api/gettoken_new 的映射

    <servlet>
        <servlet-name>GetTokenServlet</servlet-name>
        <servlet-class>
            com.gxfcsoft.framework.core.GetTokenServlet
        </servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>GetTokenServlet</servlet-name>
        <url-pattern>/api/gettoken_new</url-pattern>
    </servlet-mapping>

直接看 com.gxfcsoft.framework.core.GetTokenServlet 实现逻辑

  protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    Calendar c = Calendar.getInstance();
    String start_date = DateUtil.getDateTime(c);
    String errorInfo = "";
    String resultInfo = "";
    boolean isSuccess = false;
    String remoteAddr = req.getRemoteAddr();
    String remoteHost = req.getRemoteHost();
    String remoteUser = req.getRemoteUser();
    int remotePort = req.getRemotePort();
    String path = req.getPathInfo();
    if (path == null || path.isEmpty())
      path = req.getRequestURI().substring(req.getContextPath().length()); 
    String username = "";
    req.setCharacterEncoding("UTF-8");
    resp.setCharacterEncoding("UTF-8");
    JSONObject json = new JSONObject();
    String appid = req.getParameter("appid");
    String userid = req.getParameter("userid");
    String appkey = req.getParameter("appkey");
    String appsecret = req.getParameter("appsecret");
    json = checkParams(appid, userid, appkey, appsecret, json);
    if (json.isEmpty()) {
      appsecret = appsecret.replace(" ", "+");
      Element element = queryObject(appid, appsecret, appkey);

跟进checkParams 方法看下

  public JSONObject checkParams(String appid, String userid, String appkey, String appsecret, JSONObject json) {
    if (StringUtil.isEmpty(appid)) {
      json.put("flag", "1");
      json.put("msg", String.valueOf(appid) + "为空!");
    } 
    if (StringUtil.isEmpty(userid)) {
      json.put("flag", "1");
      json.put("msg", String.valueOf(userid) + "为空!");
    } 
    if (StringUtil.isEmpty(appkey)) {
      json.put("flag", "1");
      json.put("msg", String.valueOf(appkey) + "为空!");
    } 
    if (StringUtil.isEmpty(appsecret)) {
      json.put("flag", "1");
      json.put("msg", String.valueOf(appsecret) + "为空!");
    } 
    return json;
  }

判断这些参数是否为空。继续跟进queryObject 方法

  public Element queryObject(String appid, String appsecret, String appkey) {
    Connection conn = null;
    try {
      conn = ResManager.getConnection("default");
      UserState us = new UserState();
      us.setCorpName("default");
      CommonDao cDao = new CommonDao(conn, us);
      String select_sql = "select top 1 * from iauthregister where appid = '" + appid + "' and appsecret = '" + appsecret + "' and appkey = '" + appkey + "' ";
      Element element = cDao.findOne(select_sql);
      return element;
    } catch (SQLException e) {
      e.printStackTrace();
      return null;
    } finally {
      if (conn != null)
        ResManager.freeConnection("default", conn); 
    } 
  }

到这就很明了了,参数appid、appsecret和appkey未经过任何过滤或校验就被直接拼接进SQL语句中,从而导致SQL注入漏洞。

补丁修复也很直接,正则检测是否包含危险字符串

漏洞复现

GET /api/gettoken_new?appid='SQLI_POC&appkey=1&appsecret=1&userid=1 HTTP/1.1
Host: u8.mrxn.net

img

延时 5 秒成功

参考


手机扫码阅读

【一日一技】快速从一堆jar包找到包含特定包名的jar

索贝内容管理系统 /sobey-mchEditor/mch/AIInt/AITaskBack XML外部实体注入(XXE)漏洞

评 论