概述
4.1⾥,這⼏個危險Transformer類不再實現 Serializable 接⼝,也就是説,他們⼏個徹底⽆法序列化和反序列化了
CommonCollections1鏈
適用環境
commons-collections3.1-3.2.1
jdk1.7.1以下
TransformedMap_readObject觸發
大體思路
- AnnotationInvocationHandler#readObject()
- TransformedMap#put()
- transformerChain#transform()
- ConstantTransformer#transform() InvokerTransformer#transform()
細節問題在p神的《java安全漫談》-10會詳細解釋
- 參考鏈接:
-
- p神的《java安全漫談》-9,10
LazyMap_invoke觸發
大體思路
AnnotationInvocationHandler實現了InvocationHandler接口,這在動態代理中相當於是重寫了invoke()函數去解決下面問題
當通過代理類的對象調用方法a時,如何動態的去調用被代理類中的同名方法a?
- AnnotationInvocationHandler#readObject()
當readObject()使用代理類執行任何方法時會跳轉到第2步- AnnotationInvocationHandler#invoke()
- LazyMap#get()
- transformerChain#transform()
- ConstantTransformer#transform() InvokerTransformer#transform()
- 參考鏈接
-
- p神的《java安全漫談》-11
invoke是動態代理定位方法的函數。當通過代理類對象調用方法時,會自動的調用invoke函數進而調用被代理類中同名的方法
高版本jdk如何觸發鏈
跳轉到cc6鏈
CC2鏈
適用環境
commons-collections4 4.0
TestPriorityQueueTransformingComparator
大體思路
- java.util.PriorityQueue#readObject()
- PriorityQueue#heapify()
- PriorityQueue#siftDown()
- PriorityQueue#siftDownUsingComparator()
這個函數裏調用了comparator.compare()
- org.apache.commons.collections4.comparators.TransformingComparator#compare()
- transformerChain#transform()
- ConstantTransformer#transform() InvokerTransformer#transform()
- 參考鏈接
-
- p神的《java安全漫談》-16
關於PriorityQueue隊列的文章:
CC3鏈
適用環境
commons-collections3.1-3.2.1
jdk1.7.1以下
- 關於字節碼需要注意:
這個字節碼對應的類是 com.sun.org.apache.xalan.internal.xsltc.runtime.AbstractTranslet 的子類
TemplatesImpl與InvokerTransformer
大體思路
在cc1鏈基礎上藉助TemplatesImpl::newTransformer()和ConstantTransformer構造⼀個執⾏任意字節碼的鏈
- AnnotationInvocationHandler#readObject()
- TransformedMap#put()
其實這一步也可以使用LazyMap#get()那條鏈
- transformerChain#transform()
- ConstantTransformer#transform() InvokerTransformer#transform()
這一步是獲得TemplatesImpl對象,並調用TemplatesImpl.newTransformer()函數
- 參考鏈接:
- p神的《java安全漫談》-14
TrAXFilter與InstantiateTransformer
大體思路
在cc1鏈基礎上藉助TrAXFilter和InstantiateTransformer調用TemplatesImpl::newTransformer()構造⼀個執⾏任意字節碼的鏈
- AnnotationInvocationHandler#readObject()
- TransformedMap#put()
其實這一步也可以使用LazyMap#get()那條鏈
- transformerChain#transform()
- ConstantTransformer#transform() InstantiateTransformer#transform()
這一步是獲得TrAXFilter對象,並調用TrAXFilter的構造函數,進而執行了(TransformerImpl) templates.newTransformer()
- 參考鏈接:
- p神的《java安全漫談》-14
-
高版本jdk如何觸發鏈
- 參考cc1鏈如何改進成cc6鏈
CC4鏈
適用環境
commons-collections4 4.0
其實commons-collections依賴的其它鏈還可以繼續用,只需把報錯修改一下
CC6鏈
大體思路
- java.util.HashMap#readObject()
- HashMap#hash(key)
key是Map對象
- TiedMapEntry#hashCode()
- TiedMapEntry#getValue()
這一步執行了
- LazyMap#get(key)
- transformerChain#transform()
- ConstantTransformer#transform() InvokerTransformer#transform()
參考鏈接
- p神的《java安全漫談》-12
CommonsBeanutils1鏈
適用環境
CommonsBeanutils 1.9.3
TestPriorityQueueBeanComparator
大體思路
- java.util.PriorityQueue#readObject()
- PriorityQueue#heapify()
- PriorityQueue#siftDown()
- PriorityQueue#siftDownUsingComparator()
這個函數裏調用了comparator.compare()
- BeanComparator#compare()
PropertyUtils.getProperty( o1, property ) 這段代碼,當o1是一個 TemplatesImpl 對象,而 property 的值為 outputProperties 時,將會自動調用getter,也就是TemplatesImpl#getOutputProperties() 方法
- TemplatesImpl#getOutputProperties()
Shiro利用鏈
TestTiedMapInvokerTransformer
大體思路
可以結合代碼中的註釋看
- java.util.HashMap#readObject()
- HashMap#hash(key)
- TiedMapEntry#hashCode()
- TiedMapEntry#getValue()
- LazyMap#get()
- InvokerTransformer#transform()