ブリューハイジャック:Homebrewの公式Tapを通じたマルウェア配布

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

そして、その前提のおかげで私たちは助かっています。もしダウンロードのたびに傍受されたり、警告もなくバイナリが差し替えられたりする可能性があれば、インターネットは地雷原のような場所になってしまうでしょう。

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

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

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

私たちは単に理論を唱えただけではありません。実際にインストール処理を傍受し、悪意ある.dmgファイルにすり替え、Homebrewが警告一つ発することなくそれを/Applicationsフォルダに投下する様子を確認しました。

この調査結果を公表する前に、私たちはHomebrewのメンテナーに対して責任ある情報開示プロセスを行いました。この開示を受け、Homebrewチームは影響を受けるcaskを精査し、可能な場合はHTTPSを使用するよう更新し、安全な通信手段の確保が困難な場合は完全に無効化しました。

Image

背景:Homebrew Caskの仕組み

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

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

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

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

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

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

さらに、ユーザーはサードパーティ製のtap――独自のcaskやformulaを持つ外部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)を検証し、改ざんされていないことを確認します。しかし、多くのcask――特に自動更新されるものや、バージョン番号を含まない動的なURLを使用するもの――は、この検証をスキップするためにno_checkフラグを使用しています。なぜでしょうか。こうしたケースではチェックサムが頻繁に変わるため、caskのformula内に固定のハッシュ値を維持することが現実的でない、あるいは不可能な場合があるからです。これは単なる利便性や手抜きの問題ではなく、更新の速いアプリを継続的にインストール可能にするための、ある意味で必要なトレードオフでもあります。


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

これはエコシステムの片隅にある些細な問題ではありません。実際に広く使われているアプリの例を挙げてみましょう。

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

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の組み合わせがいかに危険であるかを実証するため、私たちは簡単な概念実証を組み立てました。

対象としたのは、インストーラーをHTTP経由で取得し、チェックサム検証が無効化されているtauというcaskです。表面上はごく普通のパッケージインストールに見えますが、その裏側では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、そしてアップストリームソースから取得されるformula――これだけの規模になると、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