0x00 前言
有点回到学习Java反序列化的时光了,Java内存马的体量也很大。但我必须要提速了。
本文先认识一下Java内存马,并且再分析一次Tomcat的架构。
0x01 内存马概述
在内存马之前,主要是文件马。随着查杀技术的发展,大部分文件马的生存空间逐渐缩小,而内存马并无文件实体,只存在于内存之中,隐蔽性强,故而愈发盛行。
其实内存马由来已久,早在17年n1nty师傅的《Tomcat源码调试笔记-看不见的shell》中已初见端倪,但一直不温不火。后经过rebeyong师傅使用agent技术加持后,拓展了内存马的使用场景,然终停留在奇技淫巧上。在各类hw洗礼之后,文件shell明显气数已尽。内存马以救命稻草的身份重回大众视野。特别是今年在shiro的回显研究之后,引发了无数安全研究员对内存webshell的研究,其中涌现出了LandGrey师傅构造的Spring controller内存马。
内存马种类繁多,主要是三种类型:
- servlet-api类
- filter型
- servlet型
- spring类
- 拦截器
- controller型
- Java Instrumentation类
- agent型
在讲内存马的原理之前,需要先了解一下jsp。
0x02 JSP概述
jsp是什么
JSP(Java Server Pages)是Java的一种动态网页技术,可以看作一个Java Servlet,主要用于实现Java web应用程序的用户界面部分。网页开发者们通过结合HTML代码、XHTML代码、XML元素以及嵌入JSP操作和命令来编写JSP。当第一次访问JSP页面时,Tomcat服务器会将JSP页面翻译成一个java文件,并将其编译为.class文件。JSP通过网页表单获取用户输入数据、访问数据库及其他数据源,然后动态地创建网页。
jsp环境搭建
看这篇师傅的文章:Servlet 项目搭建 | Drunkbaby’s Blog
也可以去看白日梦组长的:java内存马专题1-servlet内存马_哔哩哔哩_bilibili
jsp语法
不妨先看一下这篇教程,对jsp语法有个大致的了解:JSP 语法 | 菜鸟教程
可能还是不太理解,没关系,用到再说。
0x03 JSP文件马
在内存马之前,是传统的文件马。现在打入内存马,也往往要依靠jsp文件马。
下面是一个简单的jsp文件马,直接运行会在浏览器上会弹calc:
1 | <%@ page import="java.io.IOException" %> |
但是如何把马放入内存中呢,有两个思路:
- 利用Java Web组件:动态添加恶意组件,如Servlet、Filter、Listener等。在Spring框架下就是Controller、Intercepter。
- 修改字节码:利用Java的Instrument机制,动态注入Agent,在Java内存中动态修改字节码,在HTTP请求执行路径中的类中添加恶意代码,可以实现根据请求的参数执行任意代码。
其实核心思路就是在服务的必经之路上插入恶意程序(不是恶意文件),这样服务就必须要加载恶意程序,进而受到攻击。
0x04 Tomcat Context
怎么理解Context
看到一个很有趣的例子,我想引用一下:
根据yzddmr6师傅的理解,如果把某次请求比作电影中的事件,那么context就相当于事件发生的背景。例如一部电影中的某个镜头中,张三大喊“奥利给”,但是只看这一个镜头我们不知道到底发生了什么,张三是谁,为什么要喊“奥利给”。所以就需要交代当时事情发生的背景。张三是吃饭前喊的奥利给?还是吃饭后喊的奥利给?因为对于同一件事情:张三喊奥利给这件事,发生的背景不同意义可能是不同的。吃饭前喊奥利给可能是饿了的意思,吃饭后喊奥利给可能是说吃饱了的意思。
在WEB请求中也如此,在一次request请求发生时,背景,也就是context会记录当时的情形:当前WEB容器中有几个filter,有什么servlet,有什么listener,请求的参数,请求的路径,有没有什么全局的参数等等。
我个人将Context称之为“上下文”。
ServletContext
理解了Context(上下文)的概念,那么ServletContext也不难理解了,就是Servlet容器内的Context。
ServletContext作为一个接口,一般的servlet都要实现该接口。读者不妨自行看一下Servlet的源码,可以看到ServletContext接口中定义了很多操作,能对Servlet中的各种资源进行访问、添加、删除等。
ApplicationContext
说了那么多,跟Tomcat有什么关系呢?
有的兄弟,有的。在Tomcat中,ServletContext规范的实现是ApplicationContext,因为门面模式的原因,实际套了一层ApplicationContextFacade。其中ApplicationContext实现了ServletContext规范定义的一些方法,例如addServlet,addFilter等
StandardContext
在ApplicationContext类中,对资源的各种操作实际上是调用了StandardContext中的方法,所以ApplicationContext的构造器首先就是要获得StandardContext。
ApplicationContext调用自身的 getRequestCharacterEncoding()方法,实际上是调用StandardContext的 getRequestCharacterEncoding()方法:
三个Context的关系
用一张图来可以表示三个Context的关系:
有一段话总结的不错:
ServletContext接口的实现类为ApplicationContext类和ApplicationContextFacade类,其中ApplicationContextFacade是对ApplicationContext类的包装。我们对Context容器中各种资源进行操作时,最终调用的还是StandardContext中的方法,因此StandardContext是Tomcat中负责与底层交互的Context。
0x05 小结
加快进度是以保证质量为前提!参考教程: