Java安全之反序列化回显与内存码

0x00 前言#

按照我个人的理解来说其实只要能拿到Request 和Response对象即可进行回显的构造,当然这也是众多方式的一种。也是目前用的较多的方式。比如在Tomcat 全局存储的Request 和Response对象,进行获取后则可以在tomcat这个容器下进行回显。而某些漏洞的方式会从漏洞的位置去寻找存储Request 和Response对象的地方。

0x01 Tomcat通用回显#

根据Litch1师傅的思路来寻找request,response对象全局存储的位置基于全局储存的新思路 | Tomcat的一种通用回显方法研究

根据该文章思路得知,在Tomcat启动的时候会调用该位置的dorun方法

image.png

由图可见,调用栈会来到创建Http11Processor对象这一步,Http11Processor继承AbstractProcessor类。而AbstractProcessor类中可见有Request,Response这两对象。并且为final修饰的,赋值后不可被更改。

Java安全之反序列化回显与内存码

那么此时我们只需要获取到这个Http11Processor对象即可获取到Request,Response。继续跟进查看Http11Processor对象在哪进行存储。

Java安全之反序列化回显与内存码

调用this.register将前面创建的Http11Processor对象进行传递。而后调用processor.getRequest().getRequestProcessor()获取RequestInfo。

image.png

调用获取到的RequestInfo,这里为rp。rp的setGlobalProcessor将global进行传递,而setGlobalProcessor方法里面会调用
global.addRequestProcessor将rp添加进去。

Java安全之反序列化回显与内存码

跟进进去发现,processors为一个ArrayList,里面存储RequestInfo类型的数据。

所以整体的思路下来我们需要获取AbstractProtocol$ConnectionHandler类 -> 获取global变量 ->RequestInfo->Request–>Response。

Java安全之反序列化回显与内存码

再往后需要寻找存储AbstractProtocol类或继承AbstractProtocol类的子类。

这里寻找到的是Connector成员变量中为protocolHandler属性的值,而 Http11AprProtocol类实现了该接口。

Java安全之反序列化回显与内存码

所以获取request的处理请求是

Connector—>AbstractProtocol$ConnectoinHandler—>global—>RequestInfo—>Request—>Response

而在Tomcat启动过程红会将Connector放入Service中。

image.png

而现在获取完成的流程是

StandardService—>Connector—>AbstractProtocol$ConnectoinHandler—>RequestGroupInfo(global)–>RequestInfo------->Request-------->Response

那么这时候如何获取StandardService成为了问题的一大关键。

文中给出的方法是从
Thread.currentThread.getContextClassLoader()里面获取webappClassLoaderBase,再获取上下文中的 StandardService。

最后调用链为

WebappClassLoaderBase —>

ApplicationContext(getResources().getContext()) —> StandardService—>Connector—>AbstractProtocol$ConnectoinHandler—>RequestGroupInfo(global)—>RequestInfo------->Request-------->Response

package com;

import org.apache.catalina.Context;
import org.apache.catalina.Service;
import org.apache.catalina.connector.Connector;
import org.apache.catalina.core.ApplicationContext;
import org.apache.catalina.core.StandardContext;
import org.apache.catalina.core.StandardService;
import org.apache.coyote.AbstractProtocol;
import org.apache.coyote.RequestGroupInfo;
import org.apache.coyote.RequestInfo;
import org.apache.coyote.Response;

import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Modifier;
import java.util.ArrayList;

@WebServlet("/demoServlet")
public class demoServlet extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

        org.apache.catalina.loader.WebappClassLoaderBase webappClassLoaderBase = (org.apache.catalina.loader.WebappClassLoaderBase) Thread.currentThread().getContextClassLoader();
        StandardContext standardContext = (StandardContext) webappClassLoaderBase.getResources().getContext();

        try {
            Field context = Class.forName("org.apache.catalina.core.StandardContext").getDeclaredField("context");
            context.setAccessible(true);
            ApplicationContext ApplicationContext = (ApplicationContext)context.get(standardContext);
            Field service = Class.forName("org.apache.catalina.core.ApplicationContext").getDeclaredField("service");
            service.setAccessible(true);
            StandardService standardService = (StandardService)service.get(ApplicationContext);
            Field connectors = Class.forName("org.apache.catalina.core.StandardService").getDeclaredField("connectors");
            connectors.setAccessible(true);
            Connector[] connector = (Connector[])connectors.get(standardService);
            Field protocolHandler = Class.forName("org.apache.catalina.connector.Connector").getDeclaredField("protocolHandler");
            protocolHandler.setAccessible(true);
//            AbstractProtocol abstractProtocol = (AbstractProtocol)protocolHandler.get(connector[0]);

            Class<?>[] AbstractProtocol_list = Class.forName("org.apache.coyote.AbstractProtocol").getDeclaredClasses();

            for (Class<?> aClass : AbstractProtocol_list) {
                if (aClass.getName().length()==52){

                    java.lang.reflect.Method getHandlerMethod = org.apache.coyote.AbstractProtocol.class.getDeclaredMethod("getHandler",null);
                    getHandlerMethod.setAccessible(true);

                    Field globalField = aClass.getDeclaredField("global");
                    globalField.setAccessible(true);
                    org.apache.coyote.RequestGroupInfo requestGroupInfo = (org.apache.coyote.RequestGroupInfo) globalField.get(getHandlerMethod.invoke(connector[0].getProtocolHandler(), null));
                    Field processors = Class.forName("org.apache.coyote.RequestGroupInfo").getDeclaredField("processors");
                    processors.setAccessible(true);
                    java.util.List<RequestInfo> RequestInfo_list = (java.util.List<RequestInfo>) processors.get(requestGroupInfo);
                    Field req = Class.forName("org.apache.coyote.RequestInfo").getDeclaredField("req");
                    req.setAccessible(true);
                    for (RequestInfo requestInfo : RequestInfo_list) {

                        org.apache.coyote.Request request1 = (org.apache.coyote.Request )req.get(requestInfo);

                        org.apache.catalina.connector.Request request2 = ( org.apache.catalina.connector.Request)request1.getNote(1);
                        org.apache.catalina.connector.Response response2 = request2.getResponse();
                        response2.getWriter().write("111");

                    }
                }
            }

        } catch (NoSuchFieldException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        }

    }

    protected void doGet(HttpServletRe
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值