Brewハイジャック:Homebrewの公式Tapを通じて配布されるマルウェア

普段ソフトウェアをインストールする際、私たちはあまり深く考えません。ファイルはHTTPS経由でダウンロードされ、チェックサムが検証され、すべてが安全であるはず――そう思い込んでいるからです。

その前提があるからこそ助かっているとも言えます。もしすべてのダウンロードが傍受され得たり、警告なしにバイナリが差し替えられ得たりするなら、インターネットは地雷原と化してしまうでしょう。

しかし、もしその両方の保護が欠けていたらどうなるでしょうか。ダウンロードが暗号化されていないプレーンHTTPで配信され、しかもインストール後の検証すら行われていなかったとしたら。まさか――2026年にもなって、広く使われているパッケージマネージャーでそんなことが起こり得るはずがない、と思うかもしれません。

ところが実際に、それがHomebrewのコアcaskシステム内部で起こり得ることが分かりました。私たちはHomebrewの公式tapに含まれる20個のcaskが、極めて単純な中間者(MITM)攻撃に対して脆弱であることを発見しました。エクスプロイトも権限昇格も一切不要です。これらのパッケージは暗号化されていないHTTPでダウンロードされ、整合性検証も行われていないため、ネットワーク経路上にいる第三者であれば誰でもペイロードをマルウェアにすり替えることができてしまいます。

これらは決してマイナーなパッケージではありません。Chrome、Spotifyをはじめ、何千ものアプリを毎日何百万人もの開発者に配信している、まさにその信頼された公式コアtapの中に存在していたのです。

私たちはこれを理論上の話にとどめず、実際にインストールを傍受し、悪意ある.dmgファイルにすり替えて、Homebrewが警告一つ出すことなくそれを/Applicationsに直接配置する様子を確認しました。

この調査結果を公表する前に、私たちはHomebrewのメンテナーに対して責任ある開示プロセスを実施しました。この開示を受けて、Homebrewチームは影響を受けるcaskを精査し、可能な場合はHTTPSを使用するよう更新し、安全な転送方式が実現できない場合は該当caskを完全に無効化しました。

Image

背景:Homebrewのcaskの仕組み

この脆弱性の意味を正しく理解するには、まずHomebrewのcaskシステムが内部でどのように動作しているかを知る必要があります。

多くの人はHomebrewを、MacOS上で開発ツールをインストールするための定番コマンドラインパッケージマネージャー(brew install python, brew install gitなど)として認識しています。これがいわゆるcoreで、Homebrewのformulaeにあたり、パッケージは通常ソースからビルドされるか、バイナリとして配布されます。

しかし、.dmg.pkg、アプリバンドルといった実際のmacOSアプリケーションをインストールしたい場合は、Homebrewのcask側(brew install --cask)を使うことになります。このシステムはGUIアプリのダウンロードとインストールを担い、アイコンを/Applicationsにドラッグしたり、インストーラーをクリックして進めたりといった面倒な作業をすべて自動化してくれます。

誰がこれを管理しているのか

ここが興味深いところです。Homebrewは巨大なプロジェクトですが、その運営は根本的にコミュニティ主導です。

メインのtapである homebrew/homebrew-caskはGitHub上で管理されています。誰でもプルリクエストを送ることで新しいcaskを提案したり、既存のcaskを更新したりできます。コントリビューターが変更を提案し、メンテナーがレビューを行い、承認されればその更新は世界中のHomebrewユーザーに向けて即座に公開されます。

さらに、ユーザーはサードパーティのtap――独自のcaskやformulaeのセットを持つ外部のGitHubリポジトリ――を追加することもできます。こうしたサードパーティのtapは公式tapと同レベルの審査を受けているわけではないため、注意を怠るとより危険な遊び場になりかねません。悪意あるものや管理が行き届いていないサードパーティのtapが紛れ込めば、まったく新たな攻撃対象領域が生まれてしまいます。

とはいえ、今回は公式のhomebrew/homebrew-casktap、すなわち本流であり信頼されている情報源に的を絞ります。なぜなら、この公式tapにおいてすら、リスクは決して絵空事ではないからです。

caskをインストールすると何が起こるのか

その流れを分解してみましょう。
以下のコマンドを実行すると:

brew install --cask some-app

Homebrewは

    1. caskのformulaを解析します ― ダウンロードURL、バージョン、チェックサムといったメタデータを取得します。

    2. インストーラーを取得します ― 通常は.dmgや.pkgで、caskで定義されたURLから直接取得します。

    3. (場合によっては)チェックサムを検証します ― ここが厄介なポイントです。

なぜno_checkが存在するのか

理論上、Homebrewはダウンロードしたファイルが改ざんされていないことを確認するため、チェックサム(sha256)を検証します。しかし、自動更新されるものやバージョン番号を含まない動的なURLで配信されるcaskの多くは、この検証をスキップするno_checkフラグを使用しています。なぜなら、こうしたケースではチェックサムが頻繁に変わるため、caskのformula内に固定ハッシュを維持すること自体が現実的でない、あるいは不可能だからです。これは単なる利便性や手抜きの問題ではなく、更新が頻繁で変化の速いアプリをHomebrewでインストール可能にするために、時として避けられないトレードオフなのです。


実際、公式のメインcask tapだけを見ても、sha256 :no_checkを明示的に宣言しているcaskは2,800個以上存在します。
しかし、この整合性検証を省略することは、特に暗号化されていない通信と組み合わさった場合、信頼の連鎖に巨大な穴を開けることになります。

これはエコシステムの片隅にあるニッチな話ではありません。広く使われているアプリの話をしているのです。いくつか例を挙げましょう。

  • Google Chrome (google-chrome) → 今年だけで26万件以上のインストール
  • Spotify (spotify) → 今年だけで9万件以上のインストール
  • Steam (steam) → 今年だけで3万5千件以上のインストール
  • Google Drive (google-drive) → 今年だけで2万5千件以上のインストール

no_checkだけであれば、必ずしも致命的とは限りません。先ほど挙げた人気cask を含む多くの主要アプリケーションは、依然として安全なHTTPS接続でダウンロードを配信しています。その場合、チェックサムがなくとも、暗号化された転送層が通信中のペイロード改ざんを防いでくれます。

本当の問題が生じるのは、no_checkがHTTPと組み合わさったときです。整合性検証もなければ、通信の暗号化もない――リモートサーバーから/Applicationsフォルダへと直接、無防備なパイプがつながっているだけの状態です。ネットワーク経路上に位置する者(公共Wi-Fi、侵害されたルーター、悪意あるISPなど)であれば誰でも、このダウンロードを傍受し、任意のものにすり替えることができます。

では、この組み合わせはどれほど一般的なのでしょうか。私たちは公式のhomebrew-cask tapを調査し、プレーンなHTTPでダウンロードを配信し、かつno_checkが有効になっているcaskを20個発見しました。つまり、開発者が日々信頼を寄せているコアtapの中に、20個の「開けっ放しのドア」が存在していたということです。

私たちは何を「安全」だと思い込んでいるのか

Homebrewのcaskを支える信頼モデルは、いくつかの重要な前提に依存しています。

✅ URLで指定されているアップストリームサーバーが正当なものであり、侵害されていないこと。

✅ 転送層(理想的にはHTTPS)がダウンロードを改ざんから保護していること。

✅ Homebrew自身がダウンロードしたファイルの整合性を検証すること。

個別に見れば、これらのギャップのどれか一つだけであれば、致命傷にならない場合もあるでしょう。しかし、ペイロードの改ざん(暗号化されていないダウンロードや侵害されたサーバーによるもの)チェックサム検証の無効化の両方が組み合わさると、シームレスかつ検知不可能な攻撃を成立させる完璧な条件が整ってしまいます。まさにこの脆弱性が存在する場所です。

概念実証(PoC):Homebrewのcaskインストールを乗っ取る

no_checkとHTTPの組み合わせがいかに危険であるかを実証するため、私たちは単純な概念実証を組み立てました。

ターゲットに選んだのはtauというcaskです。このcaskはインストーラーをHTTP経由で取得し、チェックサム検証が無効化されています。表面的には単なる一つのパッケージインストールに見えますが、その内部はMITM傍受にとって完璧な攻撃ベクトルとなっています。

ステップ0:攻撃の準備

攻撃を仕掛ける前に、まず私たちは「悪意ある」.dmgファイルを用意しました。今回は、開くと「You have been hacked!」という無害なメッセージをポップアップ表示するだけの単純なアプリです。これは純粋にデモンストレーション目的でしたが、ペイロードが完全に置き換え可能であることを証明するものです。

また、中間者(MITM)傍受を行うために、私たちはネットワーク上に自らの位置を確保し、被害者のマシンとアップストリームサーバーとの間のHTTP通信を捕捉・置換できるようにしました。

ステップ1:インストールの実行

標準的なHomebrewのインストールコマンドを実行すると:

Image

ターミナルの出力を見ると、次の点がはっきりと確認できます。

  • Homebrewがアップストリームのソースにアクセスしている:
    http://tau.uoregon.edu/tau_arm64.dmg
  • SHA256の検証が一切行われていない(caskのformulaでno_checkが設定されているため)。

私たちは転送層へのアクセスを利用して、アップストリームサーバーへのリクエストを傍受し、代わりに用意しておいた「悪意ある」アプリケーションで応答しました。

Image

ステップ2:アプリをApplicationsに配置

ダウンロード後、Homebrewはそのアプリを/Applicationsに移動します。

Image

ステップ3:悪意あるペイロードの起動

インストール後、ユーザーがそのアプリを起動すると、本人が気づかないうちに、MITM攻撃の際にすり替えた悪意あるペイロードを実行してしまいます。今回のPoCでは、単純なポップアップメッセージが表示される結果となりました。

Image

これは実験室内だけの理論的なテストではありません。次の条件がすべて揃った、現実世界で再現可能な実証だったのです。

✅ インストーラーは安全でないHTTP経由で取得された。

✅ caskのformulaはno_checkを使用しており、整合性検証がスキップされていた。

✅ Homebrewは設計どおりに、このアプリをインストールし配置した。

ネットワーク経路上に位置するだけで、私たちはユーザーのシステムにシームレスに悪意あるアプリを注入することができました――プロンプトも、警告も、権限昇格も一切必要ありませんでした。

責任ある開示

この問題の影響を検証した後、私たちは影響を受けるcaskのリストとともに、調査結果をHomebrewのメンテナーに非公開で開示しました。Homebrewチームはこの報告を調査し、一元的に対応を行いました。安全に更新できるcaskはHTTPSを使用するよう変更され、安全な転送方式が選択肢とならない、あるいは保証できない場合には、該当caskを無効化しました。

このプロセスによって、私たちが特定した個々の事例は解消されましたが、同時にcaskエコシステムにおける重要な設計上の課題も浮き彫りになりました。Homebrewは今後も、正当な実用上の理由から、HTTPのダウンロードURLと`no_check`の使用の両方をサポートし続けます。 

この開示によってもたらされた追加の精査が、今後のレビューやメンテナンスの判断に役立ち、可能な限り安全な転送方式と整合性検証の一貫した利用を促すきっかけとなることを願っています。

Tapをクリーンに保つ

Homebrewのcaskエコシステムは、攻撃者のために作られたものではなく、あくまで利便性のために作られたものです。しかし、あらゆる利便性の層と同様に、前提条件が検証されないままだと、そこに亀裂が生まれます。何千ものアプリ、コミュニティが管理するcask、そしてアップストリームのソースから取得されるformulae――こうした環境では、brew install --caskという一つのコマンドにどれほど多くの信頼が組み込まれているかを、つい忘れてしまいがちです。

今回の概念実証は、単なる設定ミス以上の、より根深い問題を明らかにしています。それは、整合性検証を静かに迂回でき、安全でない通信方式がすり抜けてしまう構造的な脆弱性です。これらの要因は、単独であれば眉をひそめる程度で済むかもしれません。しかし組み合わさることで、通常の防御をすり抜け、権限管理を回避し、信頼されたインストールプロセスの陰に隠れて悪意あるコードをユーザーのマシンに直接届ける、監視の目が届かない経路が生まれてしまうのです。

発見当時、公式tap内の複数のcaskがno_checkとHTTPを組み合わせて使用していました。これらの事例はその後、更新または削除によって解消されましたが、日常的なパッケージインストールにどれほど多くの信頼が組み込まれているかを思い知らせる、有益な教訓となりました。caskエコシステムが進化を続ける中、安全な転送方式と整合性検証への継続的な注意こそが、Homebrewの利便性と安全性を両立させる鍵となります。

これはまさに、Koiが検知するために構築されたブラインドスポットそのものです。私たちのプラットフォームは、パッケージマネージャー、ブラウザ拡張機能、IDE拡張機能といったソフトウェア配信パイプラインを継続的に監視し、チェックサムの欠如や安全でない転送方式といった危険な組み合わせを、それが攻撃ベクトルとなる前に検知します。もしあなたのチームがKoiを導入していれば、この20個の脆弱なcaskは、それが環境内に現れた瞬間にフラグが立てられ、ペイロードがディスクに触れる前にブロックされていたはずです。

ソフトウェアエコシステムがより動的かつ分散化していく中、こうした見過ごされがちな信頼のギャップは今後ますます増えていくでしょう。パッケージマネージャーに頼ってエンドポイントをクリーンに保っているのであれば、今こそインストールコマンドの裏側で実際に何が流れているのかを、より深く可視化する仕組みを取り入れるべき時です。

あなたの環境を保護する方法について、ぜひ私たちにご相談ください。

翻訳元: https://www.koi.ai/blog/brew-hijack-serving-malware

本記事は koi.ai の記事を翻訳・要約したものです。