shiro550反序列化漏洞学习(没怎么学过java的人简单尝试)

shiro框架提供了rememberme这个功能,用户登陆后会生成经过加密并编码的cookie,在服务端接收cookie值后,进行解密流程

Base64解码——>AES解码——>反序列化

因此我们只需要获取AES加密的密钥,就可以构造一个恶意对象,再对其进行加密

反序列化——>AES加密——>Base64编码

然后将构造的恶意对象,将其作为cookie的rememberMe字段发送,Shiro将rememberMe进行解密并且反序列化,最终造成反系列化漏洞。

漏洞成因:

Shiro 1.2.4及之前的版本中,AES加密的密钥默认硬编码在代码里(SHIRO-550)

源码分析:

入口点:

onSuccessfulLogin(Subject subject, AuthenticationToken token, AuthenticationInfo info)函数

 

isRememberMe(token) 判断token是否为true

token为true后,进入rememberIdentity函数

跟入getIdentityToRemember函数,这个函数接收subject和AuthenticationInfo作为参数,但是忽略了subject参数,只返回AuthenticationInfo中的principals,这个函数主要用来存储用户主体,相当于把获取的用户名赋值给principals

跟入rememberIdentity函数,看到调用了convertPrincipalsToBytes函数

继续跟入convertPrincipalsToBytes函数,发现这个函数先对之前获取的用户进行反序列化,利用getCipherService()来判断返回的结果是否为空(如果AbstractRememberMeManager类中有一个CipherService属性,那么getCipherService方法就会返回这个属性的值。如果没有这个属性,那么getCipherService方法就会返回null),后进入encrypt函数

encrypt函数

定义一个变量value,初始化为参数serialized。
获取一个CipherService对象,赋值给变量cipherService。
如果cipherService不为空,执行以下操作:
调用cipherService的encrypt方法,传入参数serialized和一个加密密钥,得到一个ByteSource对象,赋值给变量byteSource。
调用byteSource的getBytes方法,得到一个字节数组,赋值给变量value。
返回变量value。

跟入这个函数

cipherService.encrypt(serialized, getEncryptionCipherKey())函数

cipherService是一个接口,encrypt是接口中的函数

在CipherService.java中发现了AesCipherService

继续跟入发现了AES,可以看出是AES加密

继续跟入继承的DefaultBlockCipherService,发现了其运行方式为CBC与填充方案是 PKCS5

跟入PKCS5,可以看出整个加密方法是AES-CBC-PKCS5Padding

回到之前的encrypt函数,这次的目标是getEncryptionCipherKey()函数

跟入getEncryptionCipherKey()函数

查看encryptionCipherKey的调用层次,会发现调用了DEFAULT_CIPHER_KEY_BYTES这个常量

查看一下这个常量,发现是由base64的硬编码,开头到这一步刚好可以分析出加解密为

反序列化——>AES-CBC-PKCS5Padding——>base64

在调用关系中可以看出,这个AbstractRememberMeManager()是继承CookieRememberMeManager,跟入后看到了熟悉的"rememberMe"

总结流程:

  1. 用户名序列化

  2. AES-CBC加密,key已知为kPH+bIxk5D2deZiIxcaaaA==

  3. Base64编码

  4. 将上述设置到cookie中的rememberme字段

提示:不怎么会java,文章可能有些错误

### Apache Shiro 1.2.4 反序列化漏洞 (CVE-2016-4437) 的原因 Apache Shiro 是一个用于 Java 应用程序的安全框架,提供身份验证、授权、加密和会话管理等功能。该漏洞的核心在于 `rememberMe` 功能的实现方式不当。当用户登录时,如果启用了 `rememberMe` 功能,则服务器会在响应头中设置一个名为 `Set-Cookie` 的字段,并附带一个经过 Base64 编码后的对象作为值[^2]。 此编码的对象实际上是通过 Java 的序列化机制生成的一个字节数组。然而,在反序列化过程中,攻击者可以通过构造恶意的序列化数据来触发远程代码执行(RCE),从而利用这一功能实施攻击[^3]。 #### 漏洞成因的具体细节 1. **RememberMe Cookie 处理逻辑缺陷**: 当客户端发送带有伪造的 RememberMe 数据请求到服务端时,Shiro 不会对这些数据做严格的校验就直接尝试将其反序列化。 2. **Java 反序列化风险**: 如果应用程序加载了某些易受攻击的类库(例如 Common Collections),那么即使输入的数据被篡改也可能会被执行任意命令操作[^4]。 --- ### 解决方案与防护措施 针对上述提到的问题可以采取如下几种解决方案: 1. **升级版本** 升级至不受影响的新版 Apache Shiro (>=1.2.5)。官方已经在后续发布版本里修复了这个问题并改进了对于 Remember Me token 的处理流程[^1]。 2. **禁用 RememberMe 功能** 对于不需要持久化登录的应用场景可以直接关闭 RememberMe 配置项以规避潜在威胁。具体做法是在配置文件或者代码初始化阶段显式调用 disable 方法: ```java DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager(); DefaultSubjectDAO subjectDAO = new DefaultSubjectDAO(); subjectDAO.setSessionStorageEvaluator(new NullSessionStorageEvaluator()); securityManager.setSubjectDAO(subjectDAO); ``` 3. **加强依赖组件安全性审查** 定期审计项目所使用的第三方 jar 文件是否存在已知脆弱点;移除不必要的危险 gadgets 类型比如 org.apache.commons.collections.functors.* 下的内容。 4. **网络边界防御手段部署** 使用 WAF(Web Application Firewall) 或 IPS(Intrusion Prevention System) 来拦截可疑流量模式,特别是那些包含 base64 加密字符串或者其他异常特征的行为。 5. **自定义 Token 校验机制** 开发团队也可以考虑重新设计一套更健壮的身份令牌解析算法代替默认实现,确保只有合法签名才能成功解码恢复原始状态信息。 --- ### 示例代码片段展示如何检测是否存在漏洞 下面给出一段简单的测试脚本用来判断目标主机是否可能遭受此类攻击的影响: ```python import requests def check_vulnerability(url): headers = {"Cookie": "rememberMe=1"} try: response = requests.get(url, headers=headers) if "Set-Cookie" in response.headers and "rememberMe=deleteMe;" in response.headers["Set-Cookie"]: print(f"[+] Vulnerable! Target responds with 'rememberMe=deleteMe'. URL: {url}") else: print(f"[-] Not vulnerable or protected by other mechanisms. URL: {url}") except Exception as e: print(f"[!] Error occurred while checking vulnerability on {url}: {e}") if __name__ == "__main__": target_url = input("Enter the target URL to test: ") check_vulnerability(target_url.strip()) ``` ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值