【安全记录】基于Tomcat的Java内存马初探

微信公众号:信安文摘

1. 前言

平时遇到可RCE的点,都是借助工具一键注入内存马,但对其中的原理并没有很清楚的了解。本文主要跟随前辈大佬的学习笔记,以Tomcat为例,初探Java内存马的实现原理。

2. 基础知识

2.1 servlet 和 filter

Servlet 主要的作用是可以动态地生产Web页面,他执行在客户端请求和服务器响应的之间。比较简单地理解就是,一个路由URL,就会有对应的servlet对这个路由进行处理。

Filter 是一段可以复用的代码,它用来拦截HTTP请求、响应、进行一些处理和转换。常见一些Javaweb项目会在 Filter 位置创建一些XSS拦截器或者SQL拦截器,用来统一处理SQL注入漏洞或者XSS漏洞。Filter 无法产生一个请求或者响应,它只能针对某一资源的请求或者响应进行修改

2.2 servlet 和 filter 的生命周期

Servlet
Servlet 的生命周期开始于Web容器的启动时,它就会被载入到Web容器内存中,直到Web容器停止运行或者重新装入servlet时候结束。这里也就是说明,一旦Servlet被装入到Web容器之后,一般是会长久驻留在Web容器之中。

  • 装入启动服务器时加载Servlet的实例
  • 初始化:web服务器启动时或web服务器接收到请求时,或者两者之间的某个时刻启动。初始化工作有init()方法负责执行完成
  • 调用:从第一次到以后的多次访问,都是只调用doGet()或doPost()方法
  • 销毁停止服务器时调用destroy()方法,销毁实例

Filter
自定义Filter的实现,一定要求javax.servlet.Filter下的三个方法的实现,它们分别是init()doFilter()destroy()

  • 启动服务器时加载过滤器的实例,并调用init()方法来初始化实例;
  • 每一次请求时都只调用方法doFilter()进行处理;
  • 停止服务器时调用destroy()方法,销毁实例。

2.3 Tomcat 的 Container – 容器组件

Tomcat中的 Container作用:

用于封装和管理 Servlet,以及具体处理Request请求,在Connector内部包含了4个子容器:

Engine,实现类为 org.apache.catalina.core.StandardEngine
Host,实现类为 org.apache.catalina.core.StandardHost
Context,实现类为 org.apache.catalina.core.StandardContext
Wrapper,实现类为 org.apache.catalina.core.StandardWrapper

这四个字容器实际上是自上向下的包含关系:

Engine:最顶层容器组件,其下可以包含多个 Host。
Host:一个 Host 代表一个虚拟主机,其下可以包含多个 Context。
Context:一个 Context 代表一个 Web 应用,其下可以包含多个 Wrapper。
Wrapper:一个 Wrapper 代表一个 Servlet

关系图如下(借用参考文章的图):

对于tomcat的目录来说,webapps目录对应的就是 Host 组件,下面的 casmanager 等一个个webapp对应的就是 Context 组件,Wrapper 就是容器内的 Servlet了

2.4 Tomcat中的启动加载顺序

加载过程在 Tomcat 的org.apache.catalina.core.StandardContext#startInternal()

@Override
protected synchronized void startInternal() throws LifecycleException {
   
//设置webappLoader 代码省略
//Standard container startup 代码省略
try {
   

// Set up the context init params
mergeParameters();

// Configure and call application event listeners
if (ok) {
   
if (!listenerStart()) {
   
log.error(sm.getString("standardContext.listenerFail"));
ok = false;
}
}
// Configure and call application filters
if (ok) {
   
if (!filterStart()) {
   
log.error(sm.getString("standardContext.filterFail"));
ok = false;
}
}
// Load and initialize all "load on startup" servlets
if (ok) {
   
if (!loadOnStartup(findChildren())){
   
log.error(sm.getString("standardContext.servletFail"));
ok = false;
}
}

// Start ContainerBackgroundProcessor thread
super.threadStart();
} finally {
   
// Unbinding thread
unbindThread(oldCCL);
}
}

从代码中可以看到,加载顺序 context-param->listeners->filters->servlets :

  1. 首先初始化 context-param 节点:mergeParameters()
  2. 接着配置和调用 listeners 并开始监听:listenerStart()
  3. 然后配置和调用 filters ,filters 开始起作用:filterStart()
  4. 最后加载和初始化配置在 load on startup 的 servlets:loadOnStartup(findChildren())

3. 内存马技术实现介绍

从 servlet3.0 开始,提供了动态注册 Servlet 、filter 、Listener,这里重点关注 Servletfilter,因为 Servlet 能够帮助我们接受 request 请求和 response 响应,并且针对传入内容进行操作,filter 也是可以做得到的。

相关函数如下:

<T extends Filter>createFilter(Java.lang.Class<T> clazz)
javax.servlet.FilterRegistration.Dynamic addFilter(String var1, String var2);
javax.servlet.FilterRegistration.Dynamic addFilter(String var1, Filter var2);
java
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值