Ruby 4.0 通用 RCE 反序列化 Gadget 链
引言 2026 年 8 月 5 日,OpenAI 披露了一群正在评估的 AI 代理已经突破其沙箱,控制了它们运行的集群的管理员权限。这部分归功于利用 Ruby 反序列化来执行命令。这引起了我们的注意,因为在 2018 年,我们发布了首个完全由标准库构建的通用 RCE 反序列化 gadget 链,且没有任何依赖关系。该链仅适用于 Ruby 版本至 2.6.10,而最近的公开链仅适用于 3.4-rc。本文发布了一个新的通用链,使得单个 Marshal.load 能够在 Ruby 4.0.6(撰写时的最新版本)上执行命令,并在 3.3 及更早版本中保持不变。该链结合了来自未开发源的新 gadget 以及旧 gadget 的新用途。 背景 序列化是将对象转换为一系列字节的过程,这些字节可以通过网络传输或存储在文件系统或数据库中。这些字节包括重建原始对象所需的所有信息。这个重建过程称为反序列化。每种编程语言通常都有其自身的本机序列化格式,可能用不同于序列化/反序列化的名称来称呼该过程。在 Ruby 的情况下,通常使用“编组”和“解编组”这两个术语,操作由 Marshal.dump 和 Marshal.load 提供。 第十三年的 Ruby 反序列化 通用 Ruby 反序列化 gadget 链始于 2018 年,建立在早期对 Ruby on Rails 的应用特定链的研究成果之上,这项通用工作随后又反馈到其后的应用特定链中。下面的一些里程碑为该链提供了基础。 2013 年 1 月 10 日 - Rails 3.2.10 远程代码执行,作者 Hailey Somerville 2013 年 1 月 31 日 - Ruby 缺陷追踪问题,作者 Hailey Somerville 2016 年 5 月 6 日 - 攻击 Ruby on Rails 应用,作者 joernchen(Phenoelit) 2018 年 11 月 8 日 - Ruby 2.x 通用 RCE 反序列化 Gadget 链,作者 Luke Jahnke (elttam) 2019 年 1 月 2 日 - CVE-2019-5420,作者 ooooooo_q 2019 年 3 月 2 日 - 使用 Ruby YAML.load 的通用 RCE,作者 Etienne Stalmans 2019 年 6 月 20 日 - 通过 Ruby on Rails Active Storage 不安全反序列化的远程代码执行,作者 Sivathmican Sivakumaran 和 Pengsu Cheng(趋势科技安全研究团队) 2021 年 1 月 7 日 - Ruby 2.x-3.x 的通用反序列化 Gadget,作者 William Bowling 2021 年 1 月 9 日 - 使用 Ruby YAML.load (版本 > 2.7)的通用 RCE,作者 Etienne Stalmans 2022 年 3 月 28 日 - Ruby 反序列化 - Gadget on Rails,作者 httpvoid 2022 年 4 月 4 日 - 第二回合:Ruby 2.x-3.x 的更新通用反序列化 Gadget,作者 William Bowling 2022 年 5 月 17 日 - Ruby 漏洞:利用危险的打开、发送和反序列化操作,作者 Ben Lincoln(Bishop Fox) 2024 年 3 月 13 日 - 在 Rubyland 中发现反序列化 Gadget 链,作者 Alex Leahu(Include Security) 2024 年 6 月 20 日 - 通过发送 JSON 执行命令?了解 Ruby 项目中不安全反序列化漏洞是如何工作的,作者 Peter Stöckli(GitHub) 2024 年 10 月 17 日 - 更新的 ruby gadget 用于 marshal 加载,作者 Leonardo Giovannini(Doyensec) 2024 年 11 月 24 日 - Ruby 3.4 通用 RCE 反序列化 Gadget 链,作者 Luke Jahnke 2024 年 12 月 3 日 - Gem::SafeMarshal 逃逸,作者 Luke Jahnke 2025 年 8 月 20 日 - Marshal 疯狂:Ruby 反序列化利用的简短历史,作者 Matt Schwager(Trail of Bits) 2026 年 8 月 5 日 - 在 Black Hat USA 2026 上,OpenAI 披露了自主 AI 代理对 Ruby(JRuby)反序列化的野外利用 2026 - Ruby 4.0 通用 RCE 反序列化 Gadget 链,作者 Luke Jahnke(本文)。 3.4 链是如何损坏的 最近的公开链在 2024 年底发布,凭借以下有效负载在 Ruby 3.4-rc 上达到了命令执行: Marshal.dump( [ Gem::SpecFetcher, to_s_wrapper( call_url_and_create_folder( "rubygems.org/quick/Marshal.4.8/bundler-2.2.27.gemspec.rz" ) ), to_s_wrapper(exec_gadget) ] ) 发布十天后,两个提交出现在 RubyGems 中,删除了它所依赖的 gadgets,每个提交都以该写作作为动机。两个提交都包含在 Ruby 3.4.0 中,这就是为什么该链在候选版本上有效而在实际版本上无效的原因。第一个提交,62b49465f8,标题为“改善 marshal_load 方法中的类型检查”,并指出它“使得更难以将这些类作为 gadgets 使用”。 Gem::Version#marshal_load 直接将反序列化值传递给构造函数而未进行验证,Gem::Version.correct? 会对其调用 to_s: def marshal_load(array) - initialize array[0] + string = array[0] + raise TypeError, "错误的版本字符串" unless string.is_a?(String) + + initialize string end 第二个提交,89ad04db86,标题为“停止在 ivars 中存储可执行名称”,并指出它“删除了这些类作为 ACE gadgets 的用法”。 Gem::Source::Git 和 Gem::Resolver::GitSet
本站免费、广告极少。如果觉得有帮助,可以请我们喝杯咖啡 —— 任何金额都对持续运营有实际帮助。
☕请我喝杯咖啡