IEEE/ACM自动化软件工程国际会议(ASE)
Java的序列化是一个有问题的功能:当对象的内部在序列化流反序列化中公开时,可能会出现格式错误的对象,这可能会触发使用输入流中的数据执行非预期代码。而在广泛使用的Java libraries(Groovy和Apache Commons Collections)中发现过任意代码执行、表达式注释、系统资源访问漏洞。
由于使用了反射、动态类加载、代理和原生方法等,所以大多数静态分析都没有太好的效果。
为了改进静态分析的缺点,本文提出了一种混合分析来检测序列化漏洞。该方法将具有反射目标的调用点视为不安全的动态接收器。分析由两步组成:第一步运行静态分析检测连接反序列化调用点和动态接收器的调用图链,还通过堆访问路径查找从反序列化对象到动态接收器的数据流。第二部使用静态分析的结果和fuzzing构建实际输入对象。通过这些对象使用从流中读取的用户输入去系统化地触发动态接收器的调用,可以视为污染。
本文把由读对象触发的方法称为蹦床方法。
分析分两步进行。第一步,静态分析以Java库作为输入,并以蹦床方法作为切入点进行即时调用图构造和点对点分析,以获取有关值流经堆的信息。堆访问路径中有对象和字段的信息,这些信息是一个从反序列对象到动态接收器的数据流。第二步,根据这些结果重建对象,蹦床对象以对象为参数执行,并验证是否能观察到源到接收器的方法执行路径。如果没有,本文将堆信息作为模糊器的种子,以探索源到接收器的执行输入。
静态分析从给定的Java库中检测:
1)带有蹦床方法的源对象,该对象开始一个调用链到动态接收器;
2)可以通过堆访问路径从源对象到达的接收器对象,也是一个动态接收器指向的参数。
指向图:为了讨论数值流,本文考虑了指向图,该图将抽象堆对象和变量作为节点,将指针操作语句作为边。指针操作是新的对象分配、本地分配、通过调用点上的返回语句和参数绑定进行过程间分配、以及来自对象字段的负载或存储。如果一个变量到图形中的位置有路径,则变量指向这个抽象位置。
本地堆分配:Java的反序列化涉及不使用常规构造函数的堆操作,标准指针无法捕获这些构造函数。分析通过创建伪对象来补偿这一点,伪对象具有递归设置为指向特定字段声明类型的可序列化对象的字段。伪对象被设置为蹦床方法的参数。
堆访问路径。为了进行动态分析,我们需要一个堆访问路径,一个从源对象到接收器对象的字段解引用序列。堆访问路径可以从指针分析期间构造的堆图中获得。堆图的顶点表示抽象对象,边表示对象字段。
在动态分析阶段,本文使用反射机制用在静态分析阶段找到的堆图上的属性构造对象,然后执行蹦床方法。插桩用来判断是否可以在动态接收器上命中调用。
因为代码内的指引,为了到达接收器,对象图需要对执行进一步改进。
fuzzing是一种自动生成随机输入的技术,本文选择基于生成的模糊测试,因为需要在语法和语义上都有效的序列化数据。为了确保输入的合法性,本文选择使用在静态分析阶段得到的堆模型来生成合法的反序列化对象图。