详解Java反序列化漏洞( 四 )


第一个参数接受的是我们put方法写入map数组的key和value
第二个参数接受的是null
第三个参数接受的是transformerChain,也就是4个对象组成的数组

详解Java反序列化漏洞

文章插图
 
调用了父类的构造方法,并且传了一个map
详解Java反序列化漏洞

文章插图
 
继续调用父类的构造方法,仍传的是map
详解Java反序列化漏洞

文章插图
 
继续往下
详解Java反序列化漏洞

文章插图
 
Map.Entry学习和详解
将output这个map类型的数组强转到Map.Entry类型的数组中,并且用next获取一组key和value
然后后面调用setValue
详解Java反序列化漏洞

文章插图
 
调用了checkSetValue
详解Java反序列化漏洞

文章插图
 
调用transform
详解Java反序列化漏洞

文章插图
 
这里的就开始遍历我们之前写入的4个实例化对象,我们来看最终触发漏洞的关键地方
第一次遍历
详解Java反序列化漏洞

文章插图
 
返回的是Runtime.class
第二次遍历
详解Java反序列化漏洞

文章插图
 
给cls了一个Runtime.class字节码文件,cls现在是Runtime类型,然后getMethod获得一个方法对象, 方法名为getMethod,指定的传参类型为String和Object,之后调用invoke实现了getMethod方法并且 传参是getRuntime
Class cls = Class.forName("java.lang.Runtime")Method method = cls.getMethod("getMethod",new Class[] { String.class, Class[].class }).invoke(cls,"getRuntime");//等价于cls.getMethod("getRuntime",null).invoke(cls.null);//等价于cls.getMethod("getRuntime",null);第三次遍历
详解Java反序列化漏洞

文章插图
 
getMethod获得一个方法对象,方法名为invoke,指定的传参类型为Object,然后调用invoke方法实现了invoke方法,传参为null
cls.getMethod("invoke",new Class[] { Object.class, Object[].class }).invoke(cls,null);//等价于cls.invoke(null,null);第四次遍历
详解Java反序列化漏洞

文章插图
 
getMethod获得一个方法对象,方法名为exec,指定传参类型为String,然后通过invoke方法实现了exec方法,传参为calc
cls.getMethod("exec",new Class[] { String.class }).invoke(cls,'calc');//等价于cls.exec("calc");总结一下思路:
InvokerTransformer为漏洞触发处ChianedTransformer为一个容器,作用是帮我们把InvokerTransformer组成一个有序的数组,让其有序遍历
Transformer为一个接口类,这里写法单纯是多态而已....
1.利用setValue触发
AbstractInputCheckedMapDecorator下的setValue进而触发InvokerTransformer的transform这个漏洞触发点
2.第二次遍历生成的相当于一个未执行的Runtime.getRuntime(),第三次遍历相当于将Runtime.getRuntime()执行,第四次循环调用了runtime下的方法exec
0×04:如何发现Java反序列化漏洞
  • 白盒
可以检索源码中对反序列化函数的调用,例如:
ObjectInputStream.readObjectObjectInputStream.readUnsharedXMLDecoder.readObjectYaml.loadXStream.fromXMLObjectMApper.readValueJSON.parseobject确定输入点后,检查class path中是否有危险库,例如上文分析的Apache Commons Collections,若有危险库直接用ysoserial梭哈
弱无危险库,则检查是否有涉及代码执行的部分,查看是否有代码编写上的bug
  • 黑盒
我们可以通过抓包这种手段来检测是否有可控输入点,序列化数据通常以ACED开头,之后两个字节为版本号,一般情况是0005,某些情况下可能是更高的数字
如果不确定字符串是否为序列化数据,我们可以利用大牛写好的工具SerializationDumper来进行检测,用法如下:
java -jar SerializationDumper-v1.0.jar aced000573720008456d706c6f796565eae11e5afcd287c50200024c00086964656e746966797400 124c6a6176612f6c616e672f537472696e673b4c00046e616d6571007e0001787074000d47656e65 72616c207374616666740009e59198e5b7a5e794b2关于摘星实验室:
摘星实验室是星云博创旗下专职负责技术研究的安全实验室,成立于2020年5月,团队核心成员均具备多年安全研究从业经验 。实验室主要致力于攻防技术人员培养、攻防技术研究、安全领域前瞻性技术研究,为公司产品研发、安全项目及客户服务提供强有力的支撑 。在技术研究方面,摘星实验室主攻漏洞挖掘及新型攻击,并将重点关注攻击溯源与黑客行为分析;与此同时,实验室还将持续关注对工业互联网领域的技术研究 。


推荐阅读