Ruby 4.0 仍能被反序列化拿下:修掉一条 Gadget 链不等于修好 Marshal
作者:韩启明|OC 政策与安全编辑
安全公司 elttam 公布了一条新的 Ruby 通用反序列化远程代码执行链。研究者在当时最新的 Ruby 4.0.6 上完成演示,并称同一条链可用于 Ruby 3.3 及之后版本,不需要目标应用额外安装 Gem。
一句话结论:RubyGems 修掉了上一条公开利用链依赖的两个 Gadget,却没有改变不可信数据进入 Marshal.load 的根本能力;攻击者只是把剩余组件换了顺序,又拼出下载、落盘和执行。
Ruby 的 Marshal 会把对象及其内部状态序列化,加载时再恢复对象。危险不只来自某个类显式执行命令,而是恢复过程会触发常量解析、自动加载、类型转换和哈希计算。只要标准库里存在足够多可组合的方法,攻击者就可能把无害动作连成执行路径。
新链先用 Gem::SpecFetcher 触发 RubyGems 自动加载,扩大可用类集合;再利用 Time 反序列化对异常的容忍,通过 Gem::URI::Generic 触发下载组件,把攻击者控制的压缩 Ruby 源码写入可写目录;最后把构造的 Gem::StubSpecification 放进 Hash 键,借恢复 Hash 时自动调用 hash,让 Gem::Specification.load 读取并执行落盘文件。

研究者指出,2024 年公开链发布后,RubyGems 很快加入类型检查并移除可控命令字段,但两个旧 Gadget 仍能在新链里承担不同任务。这个案例说明按公开 PoC 删除单个调用点只能提高攻击成本,无法让原生对象反序列化变成安全的数据格式。
这不是说任何 Ruby 4.0 程序都能被远程攻击。前提仍是应用把攻击者可控内容交给 Marshal.load,并满足联网和可写路径等条件。问题一旦存在,版本较新或“当前没有公开链”都不应被视为控制措施。
关键事实
- 影响演示:Ruby 4.0.6,研究者称可追溯至 Ruby 3.3
- 入口:应用对不可信数据调用
Marshal.load - 依赖:只使用 Ruby 与 RubyGems 默认可用组件
- 链条:自动加载、下载落盘、Hash 恢复触发执行
OC 判断
通用对象反序列化允许数据选择类型和恢复行为,本质上已经越过“只读取数据”的边界。维护者可以继续减少 Gadget,但应用侧的正确修复仍是停止加载不可信 Marshal,改用只表达数据的格式,并在迁移期给入口增加认证、签名和隔离。
为什么重要
- 对开发者:升级 Ruby 版本不能替代清理不可信
Marshal.load。 - 对维护者:修补已知 Gadget 需要配合危险 API 审计和迁移指南。
- 对安全团队:扫描应先寻找反序列化入口,而不是只匹配某条公开载荷。
评论
围绕这篇文章补充信息、提出问题或分享观察。