shiro反序列化漏洞手动检测
拿到一个目标,序列先别急着上工具。化漏shiro反序列化漏洞的洞手动检检测,核心就一句话:看返回包里的序列rememberMe字段。这个字段是化漏shiro的“身份证”,只要目标用了shiro框架,洞手动检你发一个带rememberMe的序列请求,它必然会在响应头里回显一个rememberMe=deleteMe。化漏这玩意儿就像门上的洞手动检猫眼,你不捅它,序列永远不知道里面住着谁。化漏
手动检测的洞手动检第一步,打开Burp Suite,序列随便抓个目标站的化漏登录请求。在Cookie里手动塞一个rememberMe=1,洞手动检然后发出去。看响应头——如果出现了set-cookie: rememberMe=deleteMe,恭喜,目标大概率是shiro。但这只是第一步,就像你敲了敲门,确认屋里有人,但不知道对方是不是练家子。
接下来要区分版本。shiro的漏洞利用链从1.2.4到1.4.2都有戏,但不同版本用的加密方式不一样。你手动构造一个恶意rememberMe值,比如rememberMe=123456,再发一次请求。这时候注意看响应——如果返回的还是deleteMe,说明shiro尝试解密你的值但失败了,这反而暴露了它的密钥存在。如果返回的是rememberMe=deleteMe; Path=/,那可能是1.4.2之后的版本,默认不开启硬编码密钥,你得再想想别的招。
最关键的环节是爆破密钥。shiro的默认密钥是kPH+bIxk5D2deZiIxcaaaA==,但很多开发会改成自己的。手动检测时,你可以用Python写个几十行的小脚本,把常用的密钥字典跑一遍。具体做法是:用AES-CBC加密一个简单的序列化对象(比如org.apache.shiro.subject.SimplePrincipalCollection),然后把加密结果塞进rememberMe里发过去。一旦某个密钥能让服务端正常解密并返回rememberMe=deleteMe(注意,这次是正常流程的deleteMe,不是报错的那种),你就拿到了进入后门的钥匙。
我去年测试一个金融系统时,就是靠这个笨办法搞定的。那站点的登录页干干净净,没有任何shiro的痕迹,但我在JS文件里发现了一个rememberMe的隐藏字段。手动塞值、看响应、跑密钥,前后花了不到十分钟,密钥是2Av2h/cGfagDFQb+XNVwng==,典型的开发图省事直接从网上抄的。之后的事就简单了——用ysoserial生成一个CommonsCollections5的payload,加密后打过去,直接反弹shell。
有个细节容易被忽略:手动检测时,记得把User-Agent改成正常的浏览器标识。有些WAF会拦截带恶意特征的请求,但你手动测的时候往往忘了伪装。还有,如果目标在负载均衡后面,多试几次IP,因为有时候某一台机器修了漏洞,其他机器还漏着。别问我怎么知道的——上次红队演练,我就栽在这上面,打第一台靶机时一切正常,换到第二台才发现漏洞还在。
手动检测的另一个好处是能精确判断漏洞是否真的可利用。很多自动化工具扫出来一堆shiro漏洞,但实际利用时要么密钥不对,要么版本不匹配。手动测一遍,至少能确认三个事实:目标确实用了shiro、密钥能爆破出来、反序列化链路能通。做到这三点,才算真正拿下这个漏洞。
最后说句实在话,shiro反序列化漏洞的检测门槛不高,但坑不少。手动检测虽然慢,但每一步都踩在实处,比盲目扫一堆漏洞然后被假阳性骗得团团转强多了。你花二十分钟手动确认一个真漏洞,比花两小时跑工具然后对着几十个假漏洞发呆要有意义得多。