freeBuf
主站

分类

漏洞 工具 极客 Web安全 系统安全 网络安全 无线安全 设备/客户端安全 数据安全 安全管理 企业安全 工控安全

特色

头条 人物志 活动 视频 观点 招聘 报告 资讯 区块链安全 标准与合规 容器安全 公开课

官方公众号企业安全新浪微博

FreeBuf.COM网络安全行业门户,每日发布专业的安全资讯、技术剖析。

FreeBuf+小程序

FreeBuf+小程序

擅长捉弄的内存马同学:Servlet内存马
2022-02-21 01:37:00

前言

Servlet内存马的最后一篇,和之前的分析其实差不太多,基础知识就不进行了,这篇文章就直接从加载开始说起,废话不多说直接开始吧。

一、Servlet流程分析

(一)StrandContext.startInternal方法

首先我们需要先了解一下Tomcat的加载流程,这里借用虞大大师傅的一张图。

我们通过上图Tomcat的启动流程可以得知,首先我们启动到StandardHost就会去启动StrandContext,我们和之前内存马的分析一样,我们从Contextconfig类加载配置文件开始分析,我们打好断点,然后开始查看栈信息。

跟进上图的栈信息,我们可以看到StandardHost之后就会走到StrandContext,我们跟到StrandContext进行查看。可以看到我们此时执行的是StandardContext. startInternal(),根据栈的信息,我们在this.fireLifecycleEvent 位置正在解析web.xml并启动StandardWrapper。我们继续往下看代码。

startInternal()方法在最后依次调用了listenerStart、filterStart、loadOnStartup方法,我们跟到loadOnStartup方法进行查看。

这里我们首先对children进行了一个变量,大概猜测children应该是存储servlet的变量。接下来做了一个迭代,执行了wrapper.load()对其进行加载。我们这里其实就是我们加载wrapper的地方。

(二)ContextConfig读取配置文件

到这里我们已经跟到了StandardContext加载Wrapper的位置,最关键的参数其实就是children,所以我们回到刚才ContextConfig的位置继续进行分析。首先ContextConfig读取web.xml配置文件,我们跟到configureContext()方法查看代码,首先读取到servlet后进行迭代。

接下来执行createWrapper方法创建了一个wrapper。继续向下

接下来设置了一个ServletName和ServletClass(这里其实对应的就是web.xml中的servlet),继续向下

(三)addChild启动wrapper线程

读取到Servlet配置之后,执行了addChild(wrapper)方法,我们跟进addChild()方法进行查看。

我们跳到了StandardContext.addChild(),其实servlet的添加就是在这里面进行的。我们继续跟进去简单看一下吧。

我们走到了ContainerBase.addChild(),这个类其实是一个骨架类,这里我们需要注意两个位置,一个是我们将wrapper添加到了ContainerBase的children变量中,另一个是我们最后执行到了child.start(),我们继续向下查看。

我们跳到了LifecycleBase,这个类主要是和Tomcat的生命周期有关,我们跟到this. startInternal()进行查看。

此时我们通过LifecycleBase走到了StandardWrapper.startInternal(),查看该方法其实这里本质就是调用父类的startInternal() 线程池启动。我们点击去稍微看一下super.startInternal()进行查看

我们又走到了ContainerBase.startInternal(),方法最后启动了线程。

我们执行完addChild()方法后,我们回到了ContextConfig类,继续向下查看,可以看到此时执行了webxml.getServletMappings().entrySet().iterator(),其实这里的本质是就是读取servler-mapping。

我们跟到addServletMappingDecoded()方法,跳到了StandardContext. addServletMappingDecoded()方法下,首先将servlet-name和url-pattern添加到servletMappings下,然后通过findChild方法,找到我们之前启动的wrapper(读取之前存储到ContainerBase的children变量),我们跟进查看wrapper.addMapping()方法。

我们走到了StandardWrapper.addMapping方法。将mapping(也就是url-pattern)添加到mappings变量下。

二、Servlet内存马实现

其实看到这里应该能明白添加servlet最关键的地方就是这个两个方法,所以我们接下来内存马的编写就需要一个恶意的servlet,然后通过addChind和addServletMappingDecoded将其恶意servlet注入进去。

1645377658_6212787a9f32f4b73f502.png!small?1645377662956最终成功实现内存马。

1645377755_621278db3e00791b6e809.png!small?1645377757105

可爱小尾巴~~~

我只是个基础很差 技术很菜 脚本小子里面的小菜鸡,文章里面有什么写的不对的地方,望师傅们多加指正。Servlet型内存马算是写完了,个人觉得Servlet内存马是这三个里面最难的,因为调试的时候栈里面来回的绕,有时候跳着跳着就乱了,我可太菜了/(ㄒoㄒ)/~~,文章里面可能有些地方有写的不对的地方,希望师傅们多加指正,480°叩头。

参考文章

Servlet源码分析

Java Wrapper.setServlet方法代码示例

Tomcat源码分析-启动分析(一) Lifecycle

tomcat9源码分析(三)--容器

tomcat-超详细的启动流程(start)

Java安全之基于Tomcat的Servlet&Listener内存马

# web安全 # 代码审计 # Java代码审计 # JAVA安全 # 内存马
本文为 独立观点,未经允许不得转载,授权请联系FreeBuf客服小蜜蜂,微信:freebee2022
被以下专辑收录,发现更多精彩内容
+ 收入我的专辑
+ 加入我的收藏
相关推荐
  • 0 文章数
  • 0 关注者
文章目录