Java反序列化Shiro篇01-入门与cc依赖
0x00 前言
本篇先配置环境,分析源码,给出URLDNS,最后给出cb的cc依赖的Gadget Chain。
本文尝试以独立发现的视角去寻找漏洞点,如有不妥还望海涵。
0x01 配置环境
本文基于P神所给的环境:点这里下载项目。
将shirodemo项目用IDEA打开,然后对该项目配置tomcat环境(自行下载tomcat),如图:
其余配置照上图自行调整即可,然后启动项目,如图:(我已经启动过一次,所以这里是“重新运行”)
然后shirodemo项目下会生成target目录,把该目录下的shirodemo目录部署到tmocat中,如下图:
- 找到shirodemo目录
- 部署到tomcat中
最后再重新启动一遍项目即可。登录界面如下:
0x02 分析源码
从前端开始
账户:root;密码:secret;勾选Remember me,抓包:
再抓一次包:
那一长串的rememberMe不见了,只多了一串JESSIONID。不难猜到JESSIONID用于会话跟踪。那么rememberMe和JESSIONID会不会有什么关系呢?重开项目,不勾选rememberMe,抓包:
二者一起出现,似乎没什么关系。目前先判断为rememberMe会记住我们的登录信息,而JESSIONID用于会话跟踪,井水不犯河水。
rememberMe
也不卖关子,rememberMe一长串就是漏洞点,我们希望了解rememberMe的整个工作原理。
项目搜索跟rememberMe有关的类与方法:
很明显CookieRememberMeManager类就是专门处理rememberMe的类。
这里侧重观察两个方法:rememberSerializedIdentity和getRememberedSerializedIdentity,这两个方法类似而又相反,就讲讲getRememberedSerializedIdentity。
该方法细节比较难懂,大致就是把rememberMe那一大串字符base64解码。自然而然想到解码后的字符串到哪里去,查找该函数在哪里被调用即可:
解码后的字符串会经过convertBytesToPrincipals方法并返回一个PrincipalCollection对象——这不就是反序列化的兆头吗?跟进一探究竟:
先解密再调用反序列化,两个方法都跟进看看。反序列化其实没什么好看的,确实调用了readObject方法,也没有做什么过滤,初步猜想这里存在反序列化漏洞。不难想到,这段字符串是经过加密的,跟进:
在再次跟进前注意一下第二个参数,一路跟进发现返回值是一个常量!从名字就可以猜测该常量就是密钥,而且加密算法是AES,一种对称加密算法(单钥算法)。综上所述,我们掌握了加密算法和密钥,那我们可以构造任意Java反序列化链子,先AES加密再base64编码,最后传给服务端进行反序列化进而执行反序列化漏洞!
现在我们的思路很明确了,先以URLDNS试试看此处能不能反序列化。
0x03 URLDNS探测
我专门写了反射修改属性的方法:setField,序列化方法:ser,反序列化方法:unser。这些方法就不展示了,想必对读者而言不是难事。下面看看构造URLDNS的方法:
再回到主程序生成Poc:
尝试:
先勾选rememberMe并登录跳转到index.jsp,抓包替换rememberMe。
失败。为什么?还记得前文所讲的JESSIONID吗,如果存在该键值,就不会再解析rememberMe。删除JESSIONID,再尝试,还是失败。为什么?bp不行,换DNSLog,秒出:
所以URLDNS探测的结果是此处存在Java反序列化漏洞。
0x04 cb链
Shiro项目一般有commons-beanutils库,尝试cb链:
成功弹出计算器。相信从前几篇文章一直看到这里的读者多少有一点疑惑甚至不满:你为什么不直接给出代码,一直给截图?这是为了让你们能自己写几遍代码,断绝偷懒之心。
cb库还是有cc依赖的,如果不使用cc呢?
或者,如果我只用cc呢?
0x04 结语
下文给出纯cc和无cc依赖这两种情况的解法。