java 学习日程(内存马)
内存马(基础知识)
前言
前面我跟随P牛的脚步看了一些反序列化,当然还有很多链没有跟着分析,可能考虑后面再接着跟。今天开始打算对java内存马进行一个系统化的学习,并记录一些学习过程中的知识点。
内存马是一种无文件落地马,相对于原来的普通木马有隐蔽性强的特点,原来的木马由于新webshell检测技术也更容易被检测到,随着冰蝎的java agent 类型的内存马出现,内存马又出现在大众的眼中。
目前主要的内存马方式有以下几种方式:
- 动态注册 servlet/filter/listener(使用 servlet-api 的具体实现)
- 动态注册 interceptor/controller(使用框架如 spring/struts2)
- 动态注册使用职责链设计模式的中间件、框架的实现(例如 Tomcat 的 Pipeline & Valve,Grizzly 的 FilterChain & Filter 等等)
- 使用 java agent 技术写入字节码
基础介绍
servlet
servlet介绍
借用菜鸟教程的介绍:
Java Servlet 是运行在 Web 服务器或应用服务器上的程序,它是作为来自 Web 浏览器或其他 HTTP 客户端的请求和 HTTP 服务器上的数据库或应用程序之间的中间层。
我们可以看到servlet主要是用来处理由http协议发送和传输的报文
servlet主要的工作流程我们借用一张图来展示
我们收到http请求web服务器会将我们的request和response封装成HttpServletRequest和HttpServletResponse对象,然后调用对应servlet的init()方法,该方法只在第一次请求时被调用,接着servlet会去调用service()方法处理消息,并将结果返回给HttpServletResponse对象。
servlet生命周期
服务器启动时或者第一次请求该servlet时会初始化一个servlet对象,当服务关闭时,就会调用destory()方法销毁。所以servlet的生命周期是由web容器负责。
filter
filter介绍
filter是servlet的过滤器,是对servlet的一种补充,我们在调用servlet的service()方法之前会经过对应的filter,可以对一些不合法的请求进行拦截或更改
filter基本工作原理
1、Filter 程序是一个实现了特殊接口的 Java 类,与 Servlet 类似,也是由 Servlet 容器进行调用和执行的。
2、当在 web.xml 注册了一个 Filter 来对某个 Servlet 程序进行拦截处理时,它可以决定是否将请求继续传递给 Servlet 程序,以及对请求和响应消息是否进行修改。
3、当 Servlet 容器开始调用某个 Servlet 程序时,如果发现已经注册了一个 Filter 程序来对该 Servlet 进行拦截,那么容器不再直接调用 Servlet 的 service 方法,而是调用 Filter 的 doFilter 方法,再由 doFilter 方法决定是否去激活 service 方法。
4、但在 Filter.doFilter 方法中不能直接调用 Servlet 的 service 方法,而是调用 FilterChain.doFilter 方法来激活目标 Servlet 的 service 方法,FilterChain 对象时通过 Filter.doFilter 方法的参数传递进来的。
5、只要在 Filter.doFilter 方法中调用 FilterChain.doFilter 方法的语句前后增加某些程序代码,这样就可以在 Servlet 进行响应前后实现某些特殊功能。
6、如果在 Filter.doFilter 方法中没有调用 FilterChain.doFilter 方法,则目标 Servlet 的 service 方法不会被执行,这样通过 Filter 就可以阻止某些非法的访问请求。
filter的生命周期
- init(FilterConfig filterConfig)
- 初始化方法,只会在web应用程序启动时调用一次
- 和我们编写的Servlet程序一样,Filter的创建和销毁由WEB服务器负责。
- web 应用程序启动时,web 服务器将创建Filter 的实例对象,并调用其init方法,读取web.xml配置,完成对象的初始化功能,从而为后续的用户请求作好拦截的准备工作(filter对象只会创建一次,init方法也只会执行一次)。开发人员通过init方法的参数,可获得代表当前filter配置信息的FilterConfig对象。
- Filter对象创建之后会驻留在内存,一直服务。
- doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
- 完成实际的过滤操作。当客户请求访问与过滤器关联的URL的时候,Servlet过滤器将先执行doFilter方法。FilterChain参数用于访问后续过滤器。
- destroy();
- 销毁方法,只会在当web应用移除或服务器停止时才调用一次来卸载Filter对象。
- 通常在这个方法中,可以释放过滤器使用的资源。
filterchain(filter链)
在一个web应用当中,可以开发编写多个Filter,这些Filter组合起来称之为一个Filter链,其中每个过滤器(Filter)都可以决定是否执行下一步。
简单实现了个demo
1 | //TestFilter |
该过滤器只要访问该web服务的资源就会调用该filter
Listener
JavaWeb开发中的监听器(Listener)就是Application、Session和Request三大对象创建、销毁或者往其中添加、修改、删除属性时自动执行代码的功能组件。
ServletContextListener:对Servlet上下文的创建和销毁进行监听,监听 Web 应用的生命周期;
ServletContextAttributeListener:监听Servlet上下文属性的添加、删除和替换;
HttpSessionListener:对Session的创建和销毁进行监听。Session的销毁有两种情况,一个中Session超时,还有一种是通过调用Session对象的invalidate()方法使session失效。
HttpSessionAttributeListener:对Session对象中属性的添加、删除和替换进行监听;
ServletRequestListener:对请求对象的初始化和销毁进行监听;
ServletRequestAttributeListener:对请求对象属性的添加、删除和替换进行监听。
用途
可以使用监听器监听客户端的请求、服务端的操作等。通过监听器,可以自动出发一些动作,比如监听在线的用户数量,统计网站访问量、网站访问监控等。
这里我写了一个ServletRequestListener的demo,也就是监听请求
1 | //TestListener |
servlet api 动态注册
当我们使用tomcat注册servlet、filter和listener时主要是三种注册方式
Web.xml注册
注解注册
动态注册
web.xml注册
1 | //servlet |
注解注册即在对应类上使用注解
1 | //servlet |
动态注册
动态注册是在Web容器初始化阶段,使用ServletContext去动态注册。
一个最简单的注册servlet的demo
1 | package com.example.tomcat; |
Filter
1 | FilterRegistration.Dynamic dynamicFilter = servletContext.addFilter("DynamicFilter",new DynamicFilter()); |
addMappingForUrlPatterns中一共有三个参数EnumSet<DispatcherType> dispatcherTypes, boolean isMatchAfter, String... urlPatterns
- dispatcherTypes一共有下面几种模式,表示过滤器的类型,我们这里使用Request模式
类型 | 说明 |
---|---|
Forward | 通过RequestDispatcher的forward(),或者jsp:forward |
Include | 通过RequestDispatcher的include(),或者jsp:include |
Request | 普通模式,来自客户端的请求 |
Error | 请求错误页面来处理HTTP错误,例如404,500 |
Async | 来自AsyncContext的异步请求 |
- boolean isMatchAfter,动态注册Filter中,过滤顺序由isMatchAfter属性决定
true表示放在当前应用所有的过滤器之后,false表示将该过滤器放在当前应用所有的过滤器之前
我们注册的恶意filter优先级一定要高,放在所有过滤器之前,所以这里选false
- String… urlPatterns 表示我们要拦截的url
1 | //DynamicFilter |
参考文章: