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已经是有值的了 。

Java安全之Resin2内存马

文章插图
this._application应为上下文对象,继续往下跟通过QFilterConfig#createFilter来创建了一个Filter,之后new 了一个FilterChain
Java安全之Resin2内存马

文章插图
注意下面三个对象,添加上即可
Java安全之Resin2内存马

文章插图
_filterMap首先看FilterMap构造,主要是Regexp,QFilterConfig后面再说
Java安全之Resin2内存马

文章插图
可以反射实例化之后调用方法或者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 ,其实就是一个正则来控制的路由处理
^.*$^(?=/)|^$调用有参构造即可
Java安全之Resin2内存马

文章插图
_filtershashtable对象,key为filtername,value为QFilterConfig对象,key可以随便伪造成个正常的
Java安全之Resin2内存马

文章插图
_filterList直接add一个QFilterConfig元素即可
Java安全之Resin2内存马

文章插图
看到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);//挖掘深度为20searcher.setMax_search_depth(20);//设置报告保存位置searcher.setReport_save_path("/tmp/");searcher.searchObject();result
# RequestTargetObject = {java.lang.Thread}---> target = {com.caucho.server.TcpConnection}---> request = {com.caucho.server.http.HttpRequest}# ApplicationTargetObject = {java.lang.Thread}---> contextClassLoader = {com.caucho.java.CompilingClassLoader}---> attributes = {java.util.Hashtable}---> attributes = {com.caucho.server.http.Application}

推荐阅读