Java安全之Tomcat6 Filter內存馬

Java安全之Tomcat6 Filter內存馬回顧Tomcat8打法先回顧下之前Tomcat789的打法
這里先拋開 7 8之間的區別,在8中,最后add到filterchain的都是一個filterconfig對象
ApplicationFilterConfig包含了FilterDef對象
構造方法如下,如果當前filter屬性為null會從FilterDef取filter的實例對象
ApplicationFilterConfig(Context context, FilterDef filterDef) throws ClassCastException, ClassNotFoundException, IllegalAccessException, InstantiationException, ServletException, InvocationTargetException, NamingException, IllegalArgumentException, NoSuchMethodException, SecurityException {this.context = context;this.filterDef = filterDef;if (filterDef.getFilter() == null) {this.getFilter();} else {this.filter = filterDef.getFilter();this.getInstanceManager().newInstance(this.filter);this.initFilter();}}FilterDef中存儲了filterClass / filterName / filter 屬性
public class FilterDef implements Serializable {private static final long serialVersionUID = 1L;private static final StringManager sm;private String description = null;private String displayName = null;private transient Filter filter = null;private String filterClass = null;private String filterName = null;private String largeIcon = null;private final Map<String, String> parameters = new HashMap();private String smallIcon = null;private String asyncSupported = null;public FilterDef() {}再有就是createFilterChain中還涉及到filterMap

Java安全之Tomcat6 Filter內存馬

文章插圖
FilterMap里主要存放urlpatterner和filterName的映射
public class FilterMap extends XmlEncodingBase implements Serializable {private static final long serialVersionUID = 1L;public static final int ERROR = 1;public static final int FORWARD = 2;public static final int INCLUDE = 4;public static final int REQUEST = 8;public static final int ASYNC = 16;private static final int NOT_SET = 0;private int dispatcherMapping = 0;private String filterName = null;private String[] servletNames = new String[0];private boolean matchAllUrlPatterns = false;private boolean matchAllServletNames = false;private String[] urlPatterns = new String[0];
  • tomcat8下注入filter內存馬流程如下:
  • FilterDef: 設置 setFilter(Filter filter) setFilterName(String filterName) setFilterClass(String filterClass) 這里filterName和filterClass應該不是一個東西,最后調用StandardContext#addFilterDef將該惡意filterdef put到this.filterDefs
  • FilterMap: addURLPattern("/*") setFilterName(String filterName)setDispatcher(DispatcherType.REQUEST.name()),最后調用StandardContext#addFilterMapBefore(filtermap) 添加到this.filterMaps
  • ApplicationFilterConfig: 調用有參構造將FilterDef作為參數傳遞進去后調有參構造實例化一個ApplicationFilterConfig,最終put進standardcontext的屬性里去 。
探索Tomcat6與Tomcat8之間的區別主要看下tomcat6和tomcat8之間createFilterChain不相同的地方 看到ApplicationFilterFactory#createFilterChain
跟進getFilter
Java安全之Tomcat6 Filter內存馬

文章插圖
主要代碼如下:
所以這里構造filterDef的時候filterClass為evilfilter的全類名即可
Java安全之Tomcat6 Filter內存馬

文章插圖
再來看下FilterDef 可以發現確實在Tomcat6下面沒有filter這個屬性了
Java安全之Tomcat6 Filter內存馬

文章插圖
所以一個很大的區別就是在getFilter方法 , 也就是獲取filter實例對象的邏輯:
Tomcat8中是通過filterDef的屬性filter值來拿到 惡意filter實例
Tomcat6中是通過filterDef的屬性filterClass屬性作為類名,通過ClassLoader去實例化
Java安全之Tomcat6 Filter內存馬

文章插圖
這里當我們調用有參構造實例化ApplicationFilterConfig時,會進入getFilter方法邏輯內
Java安全之Tomcat6 Filter內存馬

文章插圖
重點看loadClass方法是否可以加載到我們的惡意filter,因為這個filter并不是真實存在,且我們也只是通過了當前線程去defineClass的
Java安全之Tomcat6 Filter內存馬

文章插圖
跟進WebappClassLoader#loadClass

推薦閱讀