^

让你的php网站拥有shiro

前言

很久很久以前freebuf发过一篇通过shiro反序列化拿下php网站的文章后,我大受震撼,震撼到今天。

我今天花了一下午摸鱼做这个实验。实验非常简单,也就是我们如何让php网站收到shiro探测的请求后让工具或脚本认为这是一个有shiro框架的网站?如何收到密钥爆破检测请求的时候,通过请求的字段值来与后端密钥做匹配,更加逼真的还原密钥爆破的场景,从而让脚本小子继续误入歧途?

Shiro框架指纹

shiro常见的指纹是通过请求包设置cookie中一个值为RememberMe=xxx,返回到有相应的Set-Cookie: rememberMe=deleteMe。这是最常见的指纹了,我们的目的是防御,而不是攻击,所以设置一个最常见的即可。

这里我拿j1anfen师傅的shiro测试工具来测试。通过原理,我们可以自己给网站base文件或者中间件写这样的代码(这里以及下文都是以php网站为例)

617a7faea15a2.png

php用$_COOKIE函数取值会使+号变成空格,这里通过headers遍历重新取值可以解决这个问题。于是我们用j1anfen师傅的工具探测一下617a7c4938e1d.png

发现已经可以让大多数工具认为我的网站是shiro框架了,但这还太简陋了。

Shiro框架密钥爆破原理

我们能不能更逼真点呢?

比如说我php网站后台指定一个密钥,你爆破密钥的时候必须和我php后台配置的密钥一致,再设置相应的回显?

https://mp.weixin.qq.com/s/do88_4Td1CSeKLmFqhGCuQ

617a7cde074d1.png

现在非常多的工具都是构造一个继承 PrincipalCollection 的序列化对象,key正确情况下不返回 deleteMe ,key错误情况下返回 deleteMe 的方式来判断key是否正确。

那么,当我们取值取到一个由密钥kPH+bIxk5D2deZiIxcaaaA==加密而来探测的rememberme,我们后端配置的密钥也是kPH+bIxk5D2deZiIxcaaaA==,我们应该怎么做呢?

首先,老版本的shiro是aes-cbc加密,padding是Pkcs7。上面key探测的方法用到了反序列化,那么解密出来的数据一定会存在反序列化的特征

aced0005

所以我们可以给后台写一下php对于aes-cbc pkcs7的解密,一开始我对aes的加密不是很熟悉。因为cbc模式下是有偏移量的,但我们并没有偏移量,让我困惑了很久为什么一个密钥就可以进行反序列化。

还是万能的小何和我说的

617a80d3e14c1.png

所以思路就很明确了:

  1. php网站收到请求中的rememberme字段值

  2. 后台存在一个我们假定的key,并使用aes-cbc解密,如果密钥匹配正确,那么解密出来的hex字符串的32-40位的字符串应该是aced0005。

  3. 如果解密出来的数据是aced0005,那么我们就不设置deleteme的头部字段。

  4. 其他情况下如果存在rememberme的请求cookie,就设置。

617a81c90fa78.png

解密脚本如下

617a81e979e0d.png

上面的pkcs7unpadding用不用结果都会有特征,去掉也行。

最终效果如下

617a8258ba0f2.png

617a8279d989d.png

成果

617a82d47560d.png

由于本人技术水平有限,一下午只能研究这么多了。后续伪造利用链,伪造回显可以继续深入研究,该继续挖漏洞了。

更新,已经初步实现这样的效果:

617ab36b1e5f5.png

光是aes解密那个部分就想了很久,一开始用的是nginx来直接配置shiro相关特征,发现我并不太行,我太菜了。

如果还有其他的伪造,其实可以用伪静态设置后缀为jsp,亦或者修改phpsession,改成jsessionid。

617a8379740c7.png

如有错误,请指正轻喷。

^^