arrayref Rustクレート ビルド時マルウェア混入事件(2026年)
何が起きたか
2026年8月20日、Rustの配列参照マクロを提供する人気クレートarrayrefのバージョン0.3.10が、悪意あるコードを含んだ状態でcrates.ioに公開された(後にcrates.ioチームが削除)。arrayref自体は正規のライブラリだが、0.3.10のマニフェストに以下の依存が追加されていた。
[dependencies.proc-macro1]
version = "1.0.107"
proc-macro1は正規のproc-macro2に似せたtyposquatting crateで、他にもproc-macro-en・aovine・arone・aronenao・tinymemberといった補助的な悪意あるクレートが関与していた。
攻撃手口: build.rsの強制実行
Cargoは宣言された依存関係を、実際にコード中で使われているかどうかに関わらずすべてビルドする。そのためarrayrefに依存を追加するだけで、proc-macro1のbuild.rs(ビルドスクリプト)が強制的に実行される。
proc-macro1 1.0.107のbuild.rsは以下を行う。
- base64フラグメントとして埋め込まれたペイロード配布サーバー
23.254.165.112:9089とC2アドレス23.254.165.112:443を実行時に再構築(難読化) rustlsとureqでTLS通信しバイナリを取得。証明書検証を無視するAcceptAll検証器を実装しており、中間者的な検査を素通りする- プラットフォーム別に実行:
- Linux/macOS:
/tmp/rust-setupにバイナリを書き込み実行権を付与して実行 - Windows: PowerShellスクリプトを
%TEMP%に書き込み、VBScriptランチャー経由で起動してプロセスを分離。ShellExecuteviaWScriptはCargoのジョブオブジェクトから逃れるため、ビルド完了後もペイロードが生き残る
- Linux/macOS:
拡散のための工作
攻撃者は0.3.5〜0.3.9をyank(取り下げ)し、非yank版が0.3.10のみになるよう仕向けた。Cargoはyank版使用時に警告を出すため、この警告に従って更新したユーザーが結果的に悪意あるバージョンへ誘導される構造になっていた。RustSecアドバイザリの報告者もこの警告に従って0.3.10へ更新した際に悪意を検知している。
影響範囲
arrayrefは全期間で約2億4,500万ダウンロード(正規の0.3.9だけで約1億5,200万)。tiny-skia・sctk-adwaita・winitを経由して依存グラフの深い位置に存在するため、egui・eframe・icedなどRustのGUIライブラリを使うプロジェクトに広く波及した。
検出指標(IOC)
- ネットワーク:
23.254.165.112のポート9089/443 - ファイル:
/tmp/rust-setup(Unix)、%TEMP%\rust-setup.ps1(Windows)
考えたこと
build.rsはコンパイル前・feature flagやコードレビューの手前で任意コードを実行できる、Cargoのエコシステム設計上の穴だと感じる。npmのpostinstallスクリプト問題と本質的に同じ構図で、パッケージマネージャが「依存を宣言したら任意コード実行が付いてくる」設計を採用している限り、ソースコード上のdiffレビューだけでは防げない。vlt (vōlt)が謳う「installと打つだけで何も勝手に実行されない設計」は、まさにこの種の攻撃への直接的な対抗策になっている。
また、yankを使ってユーザーを悪意あるバージョンへ誘導する手口は、Cargo自体の「安全側に倒すための警告UI」を逆手に取っている点が興味深い。ツールの安全機能そのものを攻撃経路に組み込む発想は、OpenSSFのScorecardのような自動スコアリングだけでは検知しづらく、OWASP Top 10:2025がA03「Software Supply Chain Failures」を独立カテゴリとして格上げした背景がよく分かる事例だと思う。
サプライチェーン攻撃の中での位置づけ: 取引先経由で物理的な生産ラインが止まる小島プレス工業の事案とは異なり、OSSの依存関係グラフというソフトウェア内部の供給網が攻撃対象になった事例。
#security #rust #supply-chain-attack