|
2016年8月15日,程命一个叫“shiro-550”的令执漏洞编号开始在安全圈疯传。那天下午我正好在客户现场,行漏对方运维主管脸色铁青地举着手机给我看——他们内网一台刚部署完Shiro框架的程命Java应用服务器,已经被某个扫描器标记成了待宰羔羊。令执不是行漏危言耸听,Apache Shiro这个当时被无数企业当作“安全守护神”的程命权限框架,自己先成了突破口。令执 问题出在“记住我”功能上。行漏Shiro把用户身份信息序列化后,程命用AES密钥加密,令执再塞进Cookie里的行漏rememberMe字段。密钥是程命硬编码的默认值,全球统一。令执这就像所有保险柜都用同一把出厂钥匙——攻击者拿到这把钥匙,行漏就能伪造任意Cookie。更致命的是,序列化数据直接丢给Java的ObjectInputStream反序列化,没做任何过滤。攻击链清晰得可怕:先反序列化构造恶意对象,再触发命令执行,服务器就此沦陷。整个过程不需要任何用户交互,一个精心构造的HTTP请求就能搞定。 我记得当时复现漏洞时,本地起了一个测试环境。用工具生成一个反弹Shell的Payload,Base64编码后塞进Cookie,发送——几秒钟后,监听端口就收到了目标机的Shell。那种感觉挺魔幻的,一个看似固若金汤的认证系统,就这么被一张“魔法Cookie”撕开了口子。那会儿网上流传的利用脚本满天飞,连不搞安全的后端开发都在群里转发,说“兄弟们赶紧改密钥”。 修复方案其实不复杂:升级到1.4.2以上版本,或者把硬编码密钥换成随机生成的强密钥。但真正麻烦的是那些已经跑在生产线上的老系统。我碰到过一家传统银行的案例,他们的核心交易系统还在用Shiro 1.2.4,改密钥意味着所有用户会话全部失效,必须强制重新登录——对银行来说,这可不是小事。最后他们只能在内网加WAF规则,手动拦截可疑的rememberMe字段特征,治标不治本地撑着。 这个漏洞最值得玩味的地方在于,它暴露出安全框架自身的“信任悖论”。Shiro本意是帮你管好身份认证,结果默认配置反而成了攻击者的万能钥匙。很多开发者以为用了成熟框架就万事大吉,却忽略了默认配置往往是最不安全的那种。别迷信“框架=安全”这个等式,Shiro这个坑,让整个Java生态都跟着反思了一遍——那些被精心封装好的“安全能力”,有时恰恰是攻击面本身。 现在再回头看,shiro-550已经成了安全教材里的经典案例。但每次看到新项目里有人图省事直接用默认配置,我还是会忍不住提醒一句:把这个AES密钥换掉,别等扫描器替你发现。毕竟,2016年那批被攻陷的服务器里,不少就是死在了“懒得改配置”这几个字上。 |