zoukankan      html  css  js  c++  java
  • Java安全之挖掘回显链

    Java安全之挖掘回显链

    0x00 前言

    前文中叙述反序列化回显只是为了拿到RequestResponse对象。在这里说的的回显链其实就是通过一连串反射代码获取到该Request对象。

    在此之前想吹爆一个项目,Java Object Searcher项目地址

    0x01 回显链挖掘

    借助Java Object Searche工具根据工具说明文档,在tomcat中下断点,然后在IDEA的Evaluate中执行索引语句。

    TargetObject = {org.apache.tomcat.util.threads.TaskThread} 
      ---> group = {java.lang.ThreadGroup} 
       ---> threads = {class [Ljava.lang.Thread;} 
        ---> [14] = {java.lang.Thread} 
         ---> target = {org.apache.tomcat.util.net.NioEndpoint$Poller} 
          ---> this$0 = {org.apache.tomcat.util.net.NioEndpoint} 
             ---> handler = {org.apache.coyote.AbstractProtocol$ConnectionHandler} 
              ---> global = {org.apache.coyote.RequestGroupInfo}
    

    根据得出结果在Evaluate中进行查看

    获取group

    编写代码获取该对象

    Field group = Class.forName("org.apache.tomcat.util.threads.TaskThread").getDeclaredField("group");
                group.setAccessible(true);
                ThreadGroup threadGroup = (ThreadGroup) group.get(thread);
    

    获取测试错误了,其原因是因为org.apache.tomcat.util.threads.TaskThread中并没有group变量,该类继承了Thread类, 该变量在Thread类中。

     Field group = Class.forName("java.lang.Thread").getDeclaredField("group");
                group.setAccessible(true);
                ThreadGroup threadGroup = (ThreadGroup) group.get(thread);
    

    获取成功。

    获取thread

    ThreadGroup threadGroup = (ThreadGroup) group.get(thread);
    Field threads = Class.forName("java.lang.ThreadGroup").getDeclaredField("threads");
    threads.setAccessible(true);
    Thread[] thread1 = (Thread[])threads.get(threadGroup);
    

    获取target

    发现thread并不是每一次都是14,需要这里采用获取线程名称进行定位对于的thread。

    if (thread2.getName().contains("http-nio")&&thread2.getName().contains("ClientPoller-1"))
    

    最终代码

    package com;
    
    import org.apache.coyote.RequestGroupInfo;
    import org.apache.coyote.RequestInfo;
    
    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.Field;
    //TargetObject = {org.apache.tomcat.util.threads.TaskThread}
    //  ---> group = {java.lang.ThreadGroup}
    //   ---> threads = {class [Ljava.lang.Thread;}
    //    ---> [14] = {java.lang.Thread}
    //     ---> target = {org.apache.tomcat.util.net.NioEndpoint$Poller}
    //      ---> this$0 = {org.apache.tomcat.util.net.NioEndpoint}
    //         ---> handler = {org.apache.coyote.AbstractProtocol$ConnectionHandler}
    //          ---> global = {org.apache.coyote.RequestGroupInfo}
    @WebServlet("/test2Servlet")
    public class test2Servlet extends HttpServlet {
        protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
            Thread thread = Thread.currentThread();
            try {
                Class<?> aClass = Class.forName("java.lang.Thread");
                Field group = aClass.getDeclaredField("group");
                group.setAccessible(true);
                ThreadGroup threadGroup = (ThreadGroup) group.get(thread);
                Field threads = Class.forName("java.lang.ThreadGroup").getDeclaredField("threads");
                threads.setAccessible(true);
                Thread[] thread1 = (Thread[])threads.get(threadGroup);
                for (Thread thread2 : thread1) {
                    if (thread2.getName().contains("http-nio")&&thread2.getName().contains("ClientPoller-1")){
                        Field target = Class.forName("java.lang.Thread").getDeclaredField("target");
                        target.setAccessible(true);
                        Object o = target.get(thread2);
                        Field this$0 = o.getClass().getDeclaredField("this$0");
                        this$0.setAccessible(true);
                        Object o1 = this$0.get(o);
                        Field handler = Class.forName("org.apache.tomcat.util.net.AbstractEndpoint").getDeclaredField("handler");
                        handler.setAccessible(true);
                        Object handler1 = handler.get(o1);
    
                        Field global = handler1.getClass().getDeclaredField("global");
                        global.setAccessible(true);
                        RequestGroupInfo requestGroupInfo = (RequestGroupInfo)global.get(handler1);
    
                        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("Success!!!");
                        }
    
    
    
                    }
                }
    //            for (Thread thread2 : thread1) {
    //                System.out.println(thread2.getName());
    //            }
    
    //            if ()
    //            thread1[14]
    //            Field target = Class.forName("java.lang.Thread").getDeclaredField("target");
    //            target.setAccessible(true);
    //            Runnable runnable = (Runnable)target.get(thread1[13]);
    
    
            } catch (ClassNotFoundException e) {
                e.printStackTrace();
            } catch (NoSuchFieldException e) {
                e.printStackTrace();
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            }
    
        }
    
        protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
            this.doPost(request, response);
        }
    }
    
    

    Reference

    半自动化挖掘request实现多种中间件回显

    0x02 结尾

    其他中间件也是同理,设置筛选条件。然后定位request进行一步步的反射获取即可。再次吹爆该项目。目前只会简单使用,其他用法待研究。

    WX:TG9yaTI1NDgyNjYxNDU= 欢迎各位师傅来一起做技术交流
  • 相关阅读:
    使用Delphi自带的TDockTabSet组件实现停靠功能(Jeremy North)
    揭秘换肤技术(转载)
    cdecl、stdcall、fastcall函数调用约定区别(转)
    Delphi XE的RTTI增强,动态Hook某些内部事件
    sizeof和strlen解析
    由swap引出的局部变量,形参和指针的小问题
    单链表的逆置算法
    关于C++中的虚拟继承的一些总结
    关于"引用"的几点说明
    求最长公共子序列(子序列在原串中可以不连续)
  • 原文地址:https://www.cnblogs.com/nice0e3/p/14897670.html
Copyright © 2011-2022 走看看