背 景
Java的序列化和反序列化工作是通过ObjectOutputStream和ObjectInputStream来完成。ObjectOutputStream的writeObject方法可以把一个java对象写入流中,ObjectinputStream的readObject方法可以从流中读取一个java对象。
在写入和读取的时候,使用的参数或返回的值是单个对象,但JAVA实际操作的是一个对象图,包括该对象所引用的其他对象,以及这些对象所引用的另外的对象。JAVA会自动遍历对象图并逐个对其进行序列化。
一段JAVA序列化和反序列化代码示例
import java.io.*;/*import java.io.ObjectOutputStream;
import java.io.ObjectInputStream;
import java.io.FileOutputStream;
import java.io.FileInputStream;*/public class Java_Test{public static void main(String args[])throws Exception {
String obj = "ls "; //将序列化对象写入文件object.txt中
FileOutputStream fos = new FileOutputStream("aa.ser");
ObjectOutputStream os = new ObjectOutputStream(fos);
os.writeObject(obj);
os.close(); // 从文件object.txt中读取数据
FileInputStream fis = new FileInputStream("aa.ser");
ObjectInputStream ois = new ObjectInputStream(fis); //通过反序列化恢复对象obj
String obj2 = (String)ois.readObject();
System.out.println(obj2);
ois.close();
}
漏洞成因及案例
既然已经知道了序列化与反序列化的过程,那么如果反序列化的时候,这些即将被反序列化的数据是恶意攻击者特殊构造的,会导致什么发生呢?
如果Java应用对用户输入,即不可信数据做了反序列化处理,那么攻击者可以通过构造恶意输入,让反序列化产生非预期的对象,非预期的对象在产生过程中就有可能带来任意代码执行等一系列后果。
Apache Commones Collections
反序列化漏洞案例
Apache Commons Collections组件被广泛应用于各种java应用的开发,其包含InvokerTransformer类可以通过调用java的反射机制来调用任意函数,其漏洞利用过程如下:
1.敏感的InvokerTransformer的transform(Object input)方法,可以通过调用Java的反射机制来调用任意函数;
2.ConstantTransformer中的transform(Object input)方法只返回传如对象,可以通过ConstantTransformer控制InvokerTransformer中的Object类型对象;
3.ChainedTransformer类串联所有Transformer的transform()方法;
这样形成了一个执行任意代码的执行链,当java每次读取序列化对象时,就会触发命令执行的Transform链:
漏洞利用场景
常见的JAVA发序列化漏洞利用场景有如下集中可能:
1.信息泄露
被系列化的对象包含敏感数据的话,存在信息泄露的风险。
2.数据伪造
假设反序列化过程中没有对数据进行校验,则可以篡改被序列化的二进制流,来进行数据伪造。
3.拒绝服务
当篡改的数据不符合序列化对象的格式要求时候,可能会导致在反序列化对象的过程中抛出异常,从而拒绝服务。
4.RCE命令执行
当反序列化对象时的运行环境中存在有漏洞的jar包(如commons Collections低版本),攻击者通过构造恶意数据流可以达到命令执行的效果。
防御手段
1.对序列化的流数据进行加密
2.在传输过程中使用TLS加密传输
3.对序列化数据进行完整性校验
4.标记敏感字段,使其不进行序列化
5.通过实现validateObject方法来进行对象属性值的校验
6.使用白名单校验,如使用使用自定义的 SecObjectInputStream
7.升级包含漏洞的组件jar包、jdk版本、中间件软件版本等