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進行一步步的反射獲取即可。再次吹爆該項目。目前只會簡單使用,其他用法待研究。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章