0x00 漏洞背景
2015年11月6日,FoxGlove Security安全团队的@breenmachine 发布的一篇博客中介绍了如何利用Java反序列化漏洞,来攻击最新版的WebLogic、WebSphere、JBoss、Jenkins、OpenNMS这些大名鼎鼎的Java应用,实现远程代码执行。Apache Commons Collections这样的基础库非常多的Java应用都在用,本文将分析这个基础库来构造exp。
0x01 java序列化简介
序列化常用于将程序运行时的对象状态以二进制的形式存储于文件系统中。序列化就是把对象转换成字节流,便于保存在内存、文件、数据库中;反序列化即逆过程,由字节流还原成对象。整个过程是独立的JVM,这意味着一个对象可以被序列化在一个平台上,并反序列化一个完全不同的平台上。Java中的ObjectOutputStream类的writeObject()方法可以实现序列化,类ObjectInputStream类的readObject()方法用于反序列化。
一个类被序列化成功,两个条件必须满足:
- 这个类必须实现java.io.Serializable接口。
- 所有在类中的字段必须是可序列化的。如果一个字段不是可序列化的,必须注明短暂的。
以序列化字符串对象为例子,以下代码把字符串对象序列化后保存在本地,然后再从本地读取数据然后反序列化对象,把字符串对象打印。
import java.io.*;
public class Ser {
public static void main(String args[]) throws Exception {
String obj = "this is test!";
// 将序列化对象写入文件object.db中
FileOutputStream fos = new FileOutputStream("object.db");
ObjectOutputStream os = new ObjectOutputStream(fos);
os.writeObject(obj);
os.close();
// 从文件object.db中读取数据
FileInputStream fis = new FileInputStream("object.db");
ObjectInputStream ois = new ObjectInputStream(fis);
// 通过反序列化恢复对象obj
String obj2 = (String)ois.readObject();
System.out.println(obj2);
ois.close();
}
}
由此可知,如果Java应用对用户输入没有过滤进行了反序列化处理,那么攻击者可以通过构造恶意输入,让反序列化产生非预期的对象,非预期的对象在产生过程中满足一定条件,就有可能带来任意代码执行。
winhex看下object.db的内容
在序列化对象数据中,头4个字节存储的是 Java 序列化对象数据特有的 Magic Number 和相应的协议版本,通常为:
0xaced (Magic Number)
0x0005 (Version Number)
在具体序列化一个对象时,会遵循序列化协议进行数据封装。 Java 应用序列化对象交互的接口寻找就可以通过监测这 4 个特殊字节或者这4个字节base64变形等来进行。
0x02 漏洞原理
该漏洞的出现的根源在CommonsCollections组件中对于集合的操作存在可以进行反射调用的方法,并且该方法在相关对象反序列化时并未进行任何校验,新版本的修复方案对相关反射调用进行了限制。问题函数主要出现在org.apache.commons.collections.Transformer接口上
eclipse下双击选中Transformer,快捷键ctrl+t查看该接口有哪些实现类。
transformer的实现类中,看到了InvokerTransformer这个类,invoke是用来实现java反射函数的。跟进这个类