概述

4.1⾥,這⼏個危險Transformer類不再實現 Serializable 接⼝,也就是説,他們⼏個徹底⽆法序列化和反序列化了

CommonCollections1鏈

適用環境

commons-collections3.1-3.2.1
jdk1.7.1以下

TransformedMap_readObject觸發

大體思路

  1. AnnotationInvocationHandler#readObject()
  2. TransformedMap#put()
  3. transformerChain#transform()
  4. ConstantTransformer#transform() InvokerTransformer#transform()

細節問題在p神的《java安全漫談》-10會詳細解釋

  • 參考鏈接:

  • p神的《java安全漫談》-9,10

LazyMap_invoke觸發

大體思路

AnnotationInvocationHandler實現了InvocationHandler接口,這在動態代理中相當於是重寫了invoke()函數去解決下面問題

當通過代理類的對象調用方法a時,如何動態的去調用被代理類中的同名方法a?

  1. AnnotationInvocationHandler#readObject()
    readObject()使用代理類執行任何方法時會跳轉到第2步
  2. AnnotationInvocationHandler#invoke()
  3. LazyMap#get()
  4. transformerChain#transform()
  5. ConstantTransformer#transform() InvokerTransformer#transform()
  • 參考鏈接

  • p神的《java安全漫談》-11

invoke是動態代理定位方法的函數。當通過代理類對象調用方法時,會自動的調用invoke函數進而調用被代理類中同名的方法

高版本jdk如何觸發鏈

跳轉到cc6鏈

CC2鏈

適用環境

commons-collections4 4.0

TestPriorityQueueTransformingComparator

大體思路

  1. java.util.PriorityQueue#readObject()
  2. PriorityQueue#heapify()
  3. PriorityQueue#siftDown()
  4. PriorityQueue#siftDownUsingComparator()

這個函數裏調用了comparator.compare()

  1. org.apache.commons.collections4.comparators.TransformingComparator#compare()


  1. transformerChain#transform()
  2. 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構造⼀個執⾏任意字節碼的鏈

  1. AnnotationInvocationHandler#readObject()
  2. TransformedMap#put()

其實這一步也可以使用LazyMap#get()那條鏈

  1. transformerChain#transform()
  2. ConstantTransformer#transform() InvokerTransformer#transform()

這一步是獲得TemplatesImpl對象,並調用TemplatesImpl.newTransformer()函數

  • 參考鏈接:
  • p神的《java安全漫談》-14

TrAXFilter與InstantiateTransformer

大體思路

cc1鏈基礎上藉助TrAXFilter和InstantiateTransformer調用TemplatesImpl::newTransformer()構造⼀個執⾏任意字節碼的鏈

  1. AnnotationInvocationHandler#readObject()
  2. TransformedMap#put()

其實這一步也可以使用LazyMap#get()那條鏈

  1. transformerChain#transform()
  2. ConstantTransformer#transform() InstantiateTransformer#transform()

這一步是獲得TrAXFilter對象,並調用TrAXFilter的構造函數,進而執行了(TransformerImpl) templates.newTransformer()

  • 參考鏈接:
  • p神的《java安全漫談》-14

高版本jdk如何觸發鏈

  • 參考cc1鏈如何改進成cc6鏈

CC4鏈

適用環境

commons-collections4 4.0

其實commons-collections依賴的其它鏈還可以繼續用,只需把報錯修改一下

CC6鏈

大體思路

  1. java.util.HashMap#readObject()
  2. HashMap#hash(key)

key是Map對象


  1. TiedMapEntry#hashCode()
  2. TiedMapEntry#getValue()

這一步執行了

  1. LazyMap#get(key)
  2. transformerChain#transform()
  3. ConstantTransformer#transform() InvokerTransformer#transform()

參考鏈接

  • p神的《java安全漫談》-12

CommonsBeanutils1鏈

適用環境

CommonsBeanutils 1.9.3

TestPriorityQueueBeanComparator

大體思路

  1. java.util.PriorityQueue#readObject()
  2. PriorityQueue#heapify()
  3. PriorityQueue#siftDown()
  4. PriorityQueue#siftDownUsingComparator()

這個函數裏調用了comparator.compare()

  1. BeanComparator#compare()

PropertyUtils.getProperty( o1, property ) 這段代碼,當o1是一個 TemplatesImpl 對象,而 property 的值為 outputProperties 時,將會自動調用getter,也就是TemplatesImpl#getOutputProperties() 方法


  1. TemplatesImpl#getOutputProperties()

Shiro利用鏈

TestTiedMapInvokerTransformer

大體思路

可以結合代碼中的註釋看

  1. java.util.HashMap#readObject()
  2. HashMap#hash(key)
  3. TiedMapEntry#hashCode()
  4. TiedMapEntry#getValue()
  5. LazyMap#get()
  6. InvokerTransformer#transform()