0x01 前言
早在 2015 年 1 月 28 日, Gabriel Lawrence(@gebl)和 Chris Frohoff(@frohoff)就发布了关于反序列化的演讲,演讲中 frohoff 公开了他写的 Java 反序列化破绽应用的工具 ysoserial。关于 Java 反序列化相关破绽的背景和相关学问能够看我之前的文章《Java 反序列化取经路》。
7 年后的今天,反序列化破绽照旧是 Java 平安破绽中的当红流量明星,高危中的高危,特别在各大中间件和框架中。而与其他破绽类型不同的是,Java 反序列化应用的中心,并不是破绽的入口点,而是环境中的依赖 —— 反序列化 Gadget。
随着时间的沉淀,各个比拟常见的组件库中的 Gadget 被发掘出来,在用户量较大的 ysoserial 以及 marshalsec 中都公开了一些常见组件的链。
但是随着各个组件的更新、各种基于黑名单/过滤层的防御形式的呈现,这些常见反序列化应用 Gadget 的可用性急速降低,攻击者常常面临着在黑盒进攻时,明明找到了入口点,但是无链可用的状况。
遇到这种状况怎样办?c0ny1 师傅在 @Joshua Bloch的《effective java》 根底上提出了应用反序列化炸弹的技巧,经过耗费局部性能到达间接延时的作用,来探测 class 能否存在,文章在这里。
珂字辈师傅完成了修正 URLDNS Gadget 经过获取类 hashCode 并经过 DNSLOG 回显的方式来尝试处理此问题,项目在这里。
但是当应用链存在但由于某种缘由被 Ban 掉,或者当类存在,但是依赖版本曾经更新,关键代码位置曾经不再包含可反序列化应用的逻辑时,攻击者还是会一筹莫展。所以针对目前的反序列化破绽应用,有以下几个局限性:
- 常应用的 Gadget 就那几个,在目的环境有防御措施的状况下,简直无法应用;
- 客户端更新依赖包版本后,原有的 Gadget 将会失效;
- 目前的 Gadget 由于为了高应用性,通常是发掘在同一个依赖下的类 + JDK 自带的类组成链,但其实还能够在几个常用依赖中找能够串联起来的类。
在对 ysoserial 中全部链停止学习和跟踪后,我发现时至今日,要在一个新组件中发掘一条新链也并不容易,需求对组件的源码完成、很多关键类的关键办法的调用有十足的理解,并在积聚了一定的平安学问后再停止对 kick-off/gadget/sink 停止发掘和组成。在真实的业务代码中,开发人员援用了更多的依赖,假如手动发掘,需求的精神和时间将会指数级上升。
所以,能不能有方法可能较为快速的发掘呢?
网飞 Platform Security Team 的 Ian Haken 在 2018 年 8 月的 DEF CON 26 上给出了他的答卷:GadgetInspector。项目在这里,PPT 在这里,会议视频在这里。
依照其引见,本项目能够自动化发掘反序列化应用链。本篇文章则是对该项目的学习、研讨以及优化改造的记载。
关于项目的引见和剖析,网上曾经存在了不少优秀的文章,本文内将不再反复相关的信息,在笔者学习和研讨时,主要参考了以下几篇文章,先罗列一下,作为本文的前置学问:
- 简单了解污点剖析技术 by k0rz3n
- java反序列化应用链自动发掘工具gadgetinspector源码浅析 by threedr3am
- Java 反序列化工具 gadgetinspector 初窥 by Longofo
- GadgetInspector源码剖析 by fynch3r
0x02 明白目的
在开端改造之前,首先要明白目的:
中心目的是对包含了若干个依赖库的用户代码停止自动化发掘反序列化应用链,预期的效果是能够依据现有的学问储藏发掘在用户的整个代码环境下可能由多个依赖组成的反序列化应用链。
很多师傅在 GadgetInspector 的中心代码上停止改造,使其才能能够掩盖 fastjson/jackson/xstream 以至是常规破绽的剖析与发掘,不过本次笔者专注于反序列化破绽,对其他类型破绽将不停止掩盖。
0x03 关键流程及技术剖析
这一小节来用文字简单描绘一下 GadgetInspector 关于 “自动化发掘反序列化应用链” 这一目的的技术完成过程中的关键流程。
一句话来说,GadgetInspector 运用 ASM 对 Java 类字节码停止污点剖析来发掘反序列化应用链。思索到在很多时分不一定能拿到用户的源代码,所以这一思绪还是十分契合理想状况的。
信息搜集
GadgetInspector 运用 ASM 的 ClassReader 来读取全部类和办法的信息,运用自定义 MethodVisitor 在读取类和办法的指定位置来记载信息。记载的信息有全限定类名、类中包含的办法、办法名、办法描绘符等。
处置完根底信息后,会解析类的继承关系、办法继承关系、结构类和办法的映射等等相关信息的映射,接下来运用 DFS 算法对办法的调用链停止逆拓扑排序,其实就是运用了递归的后序遍历,并处理了环式调用和反复排序的问题,将办法复杂的调用图转为线性的序列,供后续的遍历和处置。
污点剖析
污点剖析这局部是调用链发掘的重中之重。
GadgetInspector 运用了自定义 MethodVisitor,模仿帧栈的变化,或者说是模仿本地变量表(local variables)和操作数栈(operand stack)的变化来停止污点传播的追踪,模仿的过程实践是参照了 ASM 提供的 AnalyzerAdapter 的思绪。
这一局部共分为两段,第一段是办法内的污点传播,即办法的入参能否影响到办法返回结果的剖析过程。
GadgetInspector 经过在本人模仿的栈顶数据打标志(入参索引),并在访问字段、访问其他办法等操作时依据自定义规则判别能否可以传播污点来对栈顶数据打标志或清空的方式来停止污点传播的剖析。直到办法 return 时,取出栈顶返回数据的污点标志,得到哪个入参对其形成了影响。
第二段是办法间的污点传播,即一个办法调用下一个办法时,调用者(caller)办法能否影响到被调用者(target)办法的入参的剖析过程。
同样的思绪停止办法间调用的污点剖析,运用调用者的入参索引作为污点,传播至被调用者入参时,以为其能够影响到下一个办法的调用。
Source 与 Sink
曾在《Java 反序列化取经路》中提到,反序列化 Gadget 的组成一共有三个:Kick-off,Chain,Sink。而这里的 Kick-off 在静态剖析中则称之为 Source。
关于反序列化破绽而言,普通是从重写了 readObject
等办法的逻辑开端,停止相关的调用,最终调用到一些可能形成危害的函数,如执行命令、文件写入等。
GadgetInspector 定义了一些 Source 点:重写 finalize 办法、重写 readObject 办法、InvocationHandler子类的 invoke 办法、重写 equals/hashCode 办法以及指定包下的点如 Closure 的 call/doCall 办法。
同时定义了一些 Sink 点:FileInputStream/FileOutputStream 的创立与写出、Runtime 执行命令、反射调用、URLClassLoader 实例化、URL 树立衔接等等和一些特定包下的应用点如 PyCode 等。
反序列化链的结构
有了 Source,有了 Sink,有了污点剖析的结果,就开端最终的反序列化链的结构了。
GadgetInspector 结构反序列化链从 Source 点办法动身,寻觅该办法能污染的办法,并从这个办法和他子类中的办法中继续寻觅下一个能污染的办法,直到遇到 Sink 点,就组成了应用链。
0x04 改造之路
在理解了完成思绪,过了一遍源代码后,能够发如今局部详细细节中,GadgetInspector 还是存在着一些问题,这些问题招致着很大水平的误报和漏报,固然 Soundness 和 Completeness 永远是需求均衡的,但是这里还是能够经过一些细节的处置来对其功用停止优化和进步。
继承办法
在结构反序列化应用链时,会依据之前生成的污点传播信息获取一个办法可以污染的办法,并判别这个办法所在类和他的子类能否存在能够反序列化的类,再停止进一步的查找。
这个逻辑就存在一个问题,在 GadgetInspector 标志一个办法时,对办法的签名参加了所在类的信息,那假如一个类的办法是继承至其父类的办法,那可能会招致获取这个类的办法时的结果为空,从而漏掉了调用链的结构。
因而需求在结构链时对继承至父类的办法停止处置。
【来自 threedr3am 师傅的版本】
途径爆炸
在循环过程中,由于各种缘由可能招致最终得到的调用链十分之长,并且中间具有屡次反复性的调用办法的状况。
需求停止去重和对调用链中办法呈现的次数增加阈值等处置。
【来自 5wimming 师傅的版本】
transient 字段
标识着 transient 的字段将不会参加到序列化和反序列化的流程中,这是众所周知的事实,因而 GadgetInspector 在搜集信息和污点剖析过程中遇到 transient 修饰的字段时都停止了疏忽。
但实践上,transient 字段只代表开发人员不希望 Java 原生序列化流程来处置它,不代表开发人员本人不会处置它,可能经过自定义 writeObject/readObject 办法内的逻辑来复原对象的状态,因而<font color=”red”> transient 修饰字段的对象不会被自动反序列化,但是能够参与反序列化流程,前提是用户在调用前对其停止了处置。</font>
例如 ysoserial 中的 MozillaRhino1 链中用到的 org.mozilla.javascript.MemberBox
类,固然其成员变量都由 transient 修饰,看起来仿佛不能参与序列化/反序列化,但类中定义了 writeMember/readMember 办法用来在 writeObject/readObject 中调用中复原,照旧能够参与链条。
但作为静态剖析,不能完整开放对 transient 的限制,还是需求在某些维度停止判别。
动态代理
在运用中能够发现, GadgetInspector 是无法完好扫出经典 CC 链和一些常用的 ysoserial 中的链的,这是为什么呢?
缘由是在这些链条中,局部 gadget 之间的调用本就不是串联的,而是在结构时运用了动态代理技术,经过 InvocationHandler 完成类的 invoke 办法中的逻辑停止向后的触发。
拿 CC1 举例,是运用 AnnotationInvocationHandler 生成的动态代理类调用 AnnotationInvocationHandler#invoke
办法触发 TransformedMap#get
办法,此时能够将其作为 Source 点停止处置,GadgetInspector 就是这么做的。
但是在 Jdk7u21 等链中,则是触发调用 AnnotationInvocationHandler#equalsImpl
办法来调用代理对象的全部办法。此时则能够将其作为 Sink 点处置。
再举一个例子,在 CC3 链中,除了入口点, AnnotationInvocationHandler 还充任了代理 LazyMap 的动态代理 handler 类,串联反序列化链的作用。
除了 AnnotationInvocationHandler 之外,在一些特定的包中还有能触发特定办法的 InvocationHandler 的子类,是反序列化链的结构有更大的灵敏空间。
所以能够看到,InvocationHandler 在反序列化结构中能够起到相当大的作用,既能当 Source,又能当 Chain,还能当 Sink,因而需求对其停止格外的处置。
Agent 技术加持
GadgetInspector 是静态的剖析手腕,借助了 guava 的工具类获取指定 ClassLoader 下的全部类的资源信息,先不说 GadgetInspector 本人的依赖会污染到最终结果,还面临的问题是程序运转时从字节码动态加载,或依据某些规则动态生成的类将无法归入应用链中。
固然目前没有这样的应用链,但是理论上并不扫除,而且或许还可能绕过一些限制,因而这里产生的一个想法就是加持 Java Agent 技术来获取运转系统中全部的类。
这局部在做的时分对实践效果不报有等待,但假如效果好的话,也能够算是给 Java Agent 产品的一种赋能。
Sink/Source 点加强
这里的加强主要分为两个,一个是补充,一个是前/后置。
GadgetInspector 内置的 Sink 和 Source 点都不全,需求更完整的补充,例如 Source 点通用的只写了 ObjectInputStream#readObject
、Object#finalize/hashCode/equals
。Sink 点只写了一点点可应用的点,在目前应用手腕多种多样状况下,实践上有十分多能够补充的点。
另外一个是“ Source 点后置”以及“Sink 点前置”。在目前曾经控制到了一些根底信息后,没必要将全部的工作都交给污点剖析和最终的应用链组合逻辑。能够应用已有的学问将应用链的结构停止缩短。
例如:可用明白应用的点比方 org.apache.commons.collections.Transformer#transform
能够直接做为 sink 点,没必再走到 Method#invoke
。用动态代理生成的类作为反序列化入口时能够直接运用 java.lang.reflect.InvocationHandler#invoke
作为入口点等等。
反射
GadgetInspector 内置了一些白名单污点流,默许一些类的办法的哪几个参数能够污染返回值,其中一个如下:
{"java/lang/Class", "getMethod", "(Ljava/lang/String;[Ljava/lang/Class;)Ljava/lang/reflect/Method;", 0, 1}
感谢您的来访,获取更多精彩文章请收藏本站。
![](https://www.gyzsq.com/wp-content/uploads/2022/07/9259adea4619.gif)
1 本站一切资源不代表本站立场,并不代表本站赞同其观点和对其真实性负责。
2 本站一律禁止以任何方式发布或转载任何违法的相关信息,访客发现请向站长举报
3 本站资源大多存储在云盘,如发现链接失效,请联系我们我们会第一时间更新。
![头像](/wp-content/themes/zibll/img/avatar-default.png)