Shiro550漏洞复现分析
远程调试环境
本地搭建环境有点麻烦,索性就直接起docker,然后远程调试。进入vulnhub启动docker环境,使用exec命令进入容器
查看进程发现存在漏洞环境的jar包,docker cp 打包到本地使用jar -xvf XXX.jar解压jar包,解压完成的目录结构
将shirodemo-1.0-SNAPSHOT.jar包添加到libraries
再将BOOT-INF添加到Modules中
紧接着修改下dockerfile,如下
1 | version: '2' |
重新启动docker环境,配置idea的remote选项
在登陆处下断点,看是否能够成功
可以成功调试。可以进入下个环节了。
漏洞复现
漏洞复现的话,github上挺多工具的,下一个利用工具利用下
漏洞分析
在分析这个漏洞之前,在日常的挖洞中偶尔碰到过几次,了解过相关的漏洞原理。在服务端对rememberMe的cookie值,先base64解码然后AES解密再反序列化,就导致了反序列化RCE漏洞。
Payload产生的过程:
命令=>序列化=>AES加密=>base64编码=>RememberMe Cookie值
不过只是知道原理,对其中的利用过程没有了解过,所以也是写这篇笔记的原因。
URLDNS链
漏洞触发点在CookieRememberMeManager,双击shift查看代码,在CookieRememberMeManager这个类中存在一个rememberSerializedIdentity方法
进行base64编码,最后将base64编码字符串作为cookie的值。在下面的代码中发现了getRememberedSerializedIdentity方法,会去读取相关的信息。CookieRememberMeManager类继承了AbstractRememberMeManager,在AbstractRememberMeManager中可以找到调用rememberSerializedIdentity的方法。在rememberIdentity方法中调用
看哪个地方调用了rememberIdentity。在onSuccessfulLogin中调用了这个方法,onSuccessfulLogin这个方法能够获取输入的用户名等信息,可以在这下断点步步跟进看是如何正常生成rememberMe的Cookie信息的.
传入之后进入到onSuccessfulLogin方法中,先调用了forgetIdentity清除相关的认证信息。
进入if判断,需要满足的条件有
Token不为null,token的类型为RememberMeAuthenticationToken。进入rememberIdentity方法可以通过getIdentityToRemember获取到我们传入的参数信息
然后再调用rememberIdentity
调用convertPrincipalsToBytes,在这个方法中会进行序列化操作并将序列化后的值赋值给byte数组
在defaultserialize下的serialize方法中完成序列化操作
回到convertPrincipalsToBytes之后开始对序列化后的byte数组进行加密操作,获取加密服务为AES-CBC加密模式,可以想到CBC加密需要有key值。
继续向下就进入加密函数encrypt中,需要注意的一点为getEncryptionCipherKey(),这个就是获取加密时候需要的key值的方法,跟进之后即可查找到默认的key值
最后把加密好的编码赋值给value之后回到rememberIdentity接着调用rememberSerializedIdentity,在rememberSerializedIdentity中在进行一次base64编码操作。
接下来将base64编码后的参数设置为cookie,这个流程就是上面所说的调用过程。
命令=>序列化=>AES加密=>base64编码=>RememberMe Cookie值
刚刚在上面提到的getRememberedSerializedIdentity和rememberSerializedIdentity,所以在AbstractRememberMeManager中肯定也存在反序列化的操作。
可以尝试去寻找下反序列化时候的利用链。首先肯定是从getRememberedSerializedIdentity来作为入手点,在AbstractRememberMeManager中getRememberedPrincipals调用了getRememberedSerializedIdentity
接着看里面的代码调用getRememberedSerializedIdentity读取subjectContext中的内容,此时跟进getRememberedSerializedIdentity进入CookieRememberMeManager类中的getRememberedSerializedIdentity方法中,获取我们传入的base64的编码,也就是构造好的rememberMe的值。
然后返回getRememberedPrincipals方法中调用convertBytesToPrincipals对base64解码后的参数进行解密的操作,解密操作完成后进行反序列化
反序列化的过程应该是这样。找个脚本生成rememberMe尝试下看是否是按照这个链进行的。
URLDNS链可以直接使用ysoserial.jar这个工具生成。
1 | import base64 |
参考链接
https://www.bilibili.com/video/BV1iF411b7bD?spm_id_from=333.999.0.0