RubyGems.org远程代码执行漏洞
发布日期:2017年10月7日
CVE编号:CVE-2017-0903
漏洞概述
RubyGems.org作为Ruby生态中广泛使用的依赖包托管服务,存在一个可通过反序列化漏洞实现远程代码执行的安全缺陷。当用户执行gem install
命令时,该平台会解析gem包中的YAML文件,而攻击者可以通过特制的恶意gem包利用不安全的YAML.load
调用执行任意代码。
技术背景
Ruby gem包实质上是tar归档文件,包含三个核心文件:
metadata.gz
:包含gem元数据的YAML文件data.tar.gz
:包含源代码的tar归档checksums.yaml.gz
:包含内容校验和的YAML文件
漏洞机理
不安全的YAML解析
虽然RubyGems.org团队在2013年已意识到YAML反序列化的风险,并通过monkey-patching方式限制了可反序列化的类白名单(2015年改用Psych.safe_load
),但补丁仅覆盖了Gem::Specification#from_yaml
方法。
在Gem::Package#verify
方法的调用链中,#read_checksums
方法存在未被修补的漏洞点:
|
|
利用链构造
攻击者通过构造特殊的YAML载荷,控制@checksums
变量为任意类的实例。关键利用点在于后续的#verify_checksums
方法中对checksums.sort
的调用。
PoC载荷结构:
|
|
执行流程
Gem::Package::TarReader#sort
触发#each
方法- 调用
Gem::Package::TarReader::Entry#read
- 通过
ActiveSupport::Cache::MemoryStore#read
获取缓存条目 ActiveSupport::Cache::Entry#value
触发Marshal.load
处理压缩数据- 恶意反序列化对象的方法调用执行攻击代码
安全启示
该漏洞揭示了YAML格式的强大表达能力带来的安全风险。在不需要复杂对象序列化的场景中,应优先选用JSON等更安全的交换格式。建议将YAML.load
重命名为YAML.unsafe_load
以明确其风险性,并推动使用带类白名单参数的安全解析方法。
致谢
感谢RubyGems.org团队运营的积极响应式漏洞赏金计划,使得该漏洞得以快速修复。