Homebrew監査レポート
(blog.trailofbits.com)- Trail of Bitsの監査では、macOS開発者エコシステムにおける事実上の標準パッケージマネージャーであるHomebrewで、予期しないコード実行とビルド完全性の低下につながる可能性が確認されたが、発見事項は致命的なレベルではなかった
- 対象範囲は、
brewCLIを含むHomebrew/brewに加え、Homebrew/actions、Homebrew/formulae.brew.sh、Homebrew/homebrew-test-botまで含み、ローカルのパッケージマネージャーとCI/CDの境界をあわせて調査した brew側の問題は、サンドボックス設定文字列のインジェクション、MD5ベースの名前空間衝突、明示されていないネットワークリソースの取り込み、macOSでのソケットピボット、sudoトークンの悪用、非ローカルURLベースのformulaインストール可能性につながった- CI/CDでは、
pull_request_targetトリガーと検証されていないworkflow_dispatch入力が、bottleビルドの改ざん、認証情報の露出、権限昇格、self-hosted GitHub Actions runnerでの永続化確保の経路になり得た - Homebrewは信頼できるformulaを前提としているが、formula自体がRuby実行コードであり、API・CLIの表面が広いため、隔離と完全性の境界を一貫して維持するのは難しい
監査範囲と対象
- Trail of Bitsは昨夏、Homebrewの監査を実施した
- 監査対象は、
brewCLIを含むHomebrew/brewと、セキュリティ上重要な隣接リポジトリ3つだった- Homebrew/actions: HomebrewのCI/CD全般で使われるカスタムGitHub Actionsリポジトリ
- Homebrew/formulae.brew.sh: インストール可能なパッケージのJSONインデックスを担当するコードベース
- Homebrew/homebrew-test-bot: Homebrewの中核的なCI/CDオーケストレーションとライフサイクル管理ルーチン
- Open Tech Fundが、インターネットインフラの中核構成要素のセキュリティを強化する活動の一環として監査を支援した
- 完全なレポートはTrail of Bitsのpublicationsリポジトリで確認できる
Homebrewが重要な理由
- Homebrewは「macOSまたはLinuxのための不足しているパッケージマネージャー」を掲げ、macOS開発者にとって事実上の標準パッケージマネージャーの役割を担っている
- 毎年数億件のパッケージインストールを処理しており、インストール対象にはGolang、Node.js、OpenSSLのような中核パッケージも含まれる
- こうしたパッケージのビルド完全性は、Homebrewを超えて下流のソフトウェアエコシステムのセキュリティにつながる
- Homebrewのcoreは、
brewCLIと利用可能なRuby APIを提供するRubyモノリスである - 2009年の開始以降、Homebrewはパッケージの信頼性と使いやすさを高めるため、構造を何度も変更してきた
- バイナリビルドであるbottleを導入した
- ローカルソースビルドに代わり、bottleをデフォルトのインストール方式にした
- 侵害された開発者マシンの影響を減らすため、bottleはCI/CDでのみビルドされるようになった
- インストール方式は次第に静的なものへ変わってきたが、中核コードベースには、ユーザー制御のRubyコードとしてDSLベースのformulaを動的にロードしていた歴史的構造が今も残っている
監査で見た攻撃境界
- ローカルの行為者が明示的な
brew installなしに、formula DSLの予期しない実行を誘発できるかを確認した - ユーザーが
brew tapを実行するだけで、tapのformula評価が予期せず発生し得るかを検討した brew install fooが想定と異なるformulaをインストールするよう、名前空間の混同や衝突を引き起こせるかを調べた- ローカルにインストールされたformulaが、Homebrewのビルド隔離メカニズムを密かに迂回または弱体化できるかも確認した
- CI/CDでは、低権限の行為者がより高い権限へピボットしたり、bottleビルドを汚染したり、永続化を作れたりするかが中心的な問いだった
brew CLIで見つかった問題
brewCLIコードベースでは、formulaごとの完全性と隔離特性を弱め得る問題が見つかった- formulaがリモートURLのような予期しない出所からロードされ得る経路も確認された
- 主な発見事項は次のとおり
- TOB-BREW-2: formulaが文字列インジェクションによってサンドボックス設定を変更でき、サンドボックス脱出につながり得る
- TOB-BREW-5: Homebrewが合成名前空間である
FormulaNamespaceに衝突可能なMD5ハッシュ関数を使用しており、攻撃者がformula間のランタイム混同を誘発できる - TOB-BREW-8: formulaが
resourcestanzaに明示しなくても、ネットワークリソースをビルドに密かに含めることができる - TOB-BREW-11: formulaがmacOSでソケットピボットを使い、ビルドサンドボックスの外へ出られる
- TOB-BREW-12: formulaがユーザーの以前のアクティブな
sudoトークンを通じて、機会主義的な権限昇格を実行できる - TOB-BREW-13:
brew installが、使用中のcurlバージョンがサポートするSFTP、SCPなどすべてのプロトコルの非ローカルURLからformulaをインストールするよう誘導され得る
- Homebrew/brewは広範にテストされているが、大きなAPI・CLI表面と非公式なローカル動作契約のため、攻撃者がサンドボックス外でローカルコードを実行する経路を見つける余地が多い
- こうした経路は、信頼できるformulaを前提とするHomebrewの中核的なセキュリティ前提を必ずしも破るものではないが、悪意あるformulaや十分に精査されていない入力を通じた予期しないformulaロードに悪用され得る
Homebrew CI/CDで見つかった問題
- HomebrewのCI/CDワークフローとアクションでも、CI/CD実行の完全性を弱め得る問題が見つかった
- 低権限ユーザーがより高い権限の位置へピボットしたり、Homebrewのself-hosted GitHub Actions runnerで永続化を得たりする可能性が確認された
- 主な発見事項は次のとおり
- TOB-BREW-18: 複数のCI/CDワークフローが
pull_request_targetトリガーを使用し、サードパーティのプルリクエストがHomebrew upstreamリポジトリのコンテキストでコードを実行できるようにしていた。これは認証情報の露出やbottleビルドの改ざんにつながり得る - TOB-BREW-23: 複数のCI/CDワークフローが、検証されていない
workflow_dispatch入力によるシェルインジェクションを許しており、ワークフローは変更できないが実行はできる低権限ユーザーの垂直移動につながり得る
- TOB-BREW-18: 複数のCI/CDワークフローが
- CI/CD固有の問題に加え、
brew関連の発見事項の一部はCI/CD環境で重要だった- TOB-BREW-6: アーカイブ展開中のサンドボックス化・隔離が不足しており、低権限のCI行為者が自動ロード・実行されるformulaや実行コードを展開させ、より高い権限コンテキストへピボットできる
- TOB-BREW-13: CIが事前に構成した信頼コンテキストにないformulaを
brew installでインストールさせ、任意コード実行と権限ピボットに利用され得る
- Homebrew CI/CDは、パッケージのライフサイクルにおける人手の介入点を減らすうえで成熟しており効果的だが、GitHub Actionsワークフローでよく見られる誤用されやすい脆弱なパターンに依存している
- 危険なワークフロートリガー
- テンプレート展開による設定、コード、データの混在
- こうしたパターンは、完全な外部行為者による永続化確保やピボットを必ずしも可能にするものではないが、rogue maintainerのような低権限の内部者がCI/CDの完全性・隔離の前提を弱めるために利用し得る
パッケージマネージャー監査が難しい理由
- Homebrewのようなパッケージ管理エコシステムは、設計上、任意のサードパーティコードをインストールして実行するため、監査境界が難しい
- 想定されたコード実行と予期しないコード実行の区別も、概して非公式で緩く定義されている
- Homebrewでは、パッケージの運搬形式であるformula自体がRuby実行コードであるため、この問題がより顕著になる
- 監査プロセスでは、Homebrew maintainers、Homebrew PLC、Homebrewセキュリティ管理者のPatrick Linnaneと緊密に協力した
1件のコメント
Hacker News の意見
この記事の著者であり、監査に参加した者の一人なので質問に答えられる
監査報告書そのものが見つけにくいなら間接リンクなので、コピーもここに置いておく: https://github.com/trailofbits/publications/blob/eb9344f2261...
素晴らしい仕事で、こうしたオープンソースソリューションでまさに探していたのは、このような体系的なレビューだった
コードレビューの焦点ではないのだろうが、オープンソースのパッケージ管理プラットフォームに内在する全般的なサプライチェーンのライフサイクル問題についての見解が気になる。新しい formula が正しい上流を指していることを保証する検証プロセスは適切なのか、ユーザーは
brew updateが今も信頼できる上流を参照しているとどう確信できるのか、ドメインが乗っ取られたらどうなるのか、formula の信頼できない上流にチームがどれほど迅速に対応できるのか、という点が核心になるこうした問題のすべてを Homebrew が解決すべきというわけではないが、エコシステムの観点では重要な検討事項だ。winget や choco にも同じ問題があり、apt や yum のような商用サポート付きリポジトリでは比較的少ない。個人的にも、多くの管理者にとっても、Windows Store を扱う際の大きな懸念でもある
最後に Homebrew チームが見ているなら、npm 風の脆弱性通知があると本当にありがたい
中国共産党の関係者が主要パッケージへの pull request 権限を得た公開事例も十分にあるし、公開されていない、あるいは握りつぶされた事例はもっと多いと思う。評判の良い主体からあまり知られていない個人へパッケージ所有権が移るだけでも、当然ながら心配になる
ソフトウェアエンジニア/エンジニアリングマネージャから VC になった立場として、こうした保証を提供するスタートアップや商用企業があるのか気になる。ただ、この問題を解決する市場規模が、独立した事業になるほど十分ではないのではないかとも懸念している
Nix に移る前は、当時 Homebrew がかなり独特な動きをしていたので MacPorts を使っていた。マルチユーザー設定ではうまく動かず、
/usr/localを所有し、自動更新とバージョン管理の欠如のせいで「自分のコンピュータでは動く」問題が多かったHomebrew でいつも不安に感じていたのは、Git ではなく GitHub URL を一時的なパッケージのように使える点だった。TOB-BREW-13 がその方式で動作したのか気になる。その機能はずっと、セキュリティ事故が起きるのを待っているだけのものに聞こえていた
いずれにせよ、macOS における Nix の監査も見てみたい。特に
nix developと関連コマンドの動作方式に欠陥があるのかが気になるHomebrew には分析データ収集があり、バージョンがあまりにも頻繁に壊れた。MacPorts ははるかに安定しているが、一部のニッチなパッケージはうまくビルドされず、tmux で terminfo の問題があった
Nix はこうした多くを再定義でき、Debian ワークステーションと home manager 設定を共有できるので良い
nix.confにsandbox = trueを入れて自分で有効化することはできるが、あれこれ壊れる可能性があるNix のサンドボックスも、実のところセキュリティ境界として設計されたものではない。サンドボックス脱出を防ぐための努力は入っておらず、ホストの多くのものがサンドボックス環境へ漏れ込む。信頼できないパッケージをビルドするなら、gVisor や完全な VM のようなものが必要だ
サンドボックス脱出バグと関連修正をざっと見た: https://github.com/Homebrew/brew/pull/17700/commits/f4e5e0c7...
これで合っているのか疑問だ。サンドボックスプロファイルに補間されて問題を起こすのを防ごうとしているようだが、この文字リストについてどれほど確信できるのか分からない
なぜそうするのか、禁止した特定の文字に何が特別なのかを説明していない。より良いメッセージなら「そうしないと ... のため、パス内の特定の文字を防ぐ。これらの文字は注意が必要だが、他の文字は問題ない理由は ...」といった内容を含んでいただろう
今このコードを書いていて何をしているか分かっていたとしても、1年後に見返したら、なぜこの変更をしたのか首をかしげることになるだろう
良いコミットメッセージの実例はここにある: https://github.com/git/git/commit/92fe7c7d42cc941ed70d6fce98...
しばらく前に
brewをnixに乗り換えた。テキスト UI は、エンドユーザー向けの使いやすさをもっと改善できるそこで brew のように簡単に
ixnay installできるように「ixnay」というラッパーまで作ったが(https://github.com/pmarreck/ixnay)、全体的な保証にはそれだけの価値がある#helpドキュメントが気に入ったREADME に ixnay について触れておいた
ほぼすべての Linux や *BSD のパッケージマネージャと比べて、Homebrew にとって大きな低スキル攻撃面であるサプライチェーンの完全性が、あまり大きく扱われていないのは少し意外です。
Homebrew のメンテナーは概してコミットやパッケージに署名せず、レビューやマージにも署名せず、コンパイル時に作者やレビュアーの署名を検証せず、別管理の CI でビルドを再現せず、GitHub でハードウェア 2 要素認証も強制していません。
brew ユーザーのセキュリティ水準は、数百人いる brew メンテナーのうち、今日いちばん運用セキュリティが悪い人の水準に縛られます。
さらに dependabot が自動でコミットを作るため、自分が制御する外部プロジェクトに悪意あるコミットを入れ、dependabot が Homebrew にアップグレードコミットを作るのを待ってから自分でマージすることもできます。Homebrew のメンテナーになるには実質的に検証がほとんどなく、簡単なバグをいくつか直せば済みます。
メンテナーの期限切れメールドメインを 1 つ取得して、パスワードリセットメールを自分に送らせ、休暇中または活動を休んでいる人のアカウントを乗っ取ることもできます。
誰かが気づく前に、数千社を侵害できる可能性は高いでしょう。
正直なところ、権限のある会社支給機器では Brew を絶対に許可しません。数百人の任意の人物と、その脆弱な運用セキュリティを悪用する誰に対しても、ユーザーのシステムで任意コードを実行する能力を与えることになるからです。
主要な Linux パッケージマネージャも、レビュー署名のような部分では十分に踏み込めていませんが、ほとんどは少なくとも作者レベルのパッケージ署名、人によるレビュー、多くのパッケージに対する独立した再現ビルドは行っています。
企業のシステム管理者のような高価値ターゲットが、自分のコンピュータで brew を許可していることが多い点を考えると、Brew は不十分なサプライチェーン管理による被害という点で、いつ Crowdstrike を超えてもおかしくない軌道上にあります。
Mac で Pacman のように PKGBUILD を同程度の性能でサポートし、主要プログラムのパッケージがきちんと維持されるなら、Mac を使う際に利便性のために受け入れなければならない妥協はずっと少なくなると思います。
Homebrew は素晴らしく、formula も本当によく維持されていますが、PKGBUILD の単純さ、同期の速さ、パッケージマネージャごとに多数の引数やフラグを覚えなければならない認知負荷の低さを考えると、pacman が Mac でそのまま動いてほしいです。
主な攻撃ベクトルは、単に新しい formula をコントリビュートして、悪意ある新規パッケージをこっそり入れられる点だと思います。
メンテナーチームは、新たにコントリビュートされるすべての formula を監査するには小さすぎます。この攻撃ベクトルが監査に含まれていないのは意外です。
たとえそうだとしても、それは記事で明示的に扱われているパッケージングの曖昧さの 1 つです。ファーストパーティ実行とサードパーティ実行の境界は本質的に曖昧であり、意図してサードパーティコードを実行したときに起こる当然のことをすべて指摘するよりも、サードパーティ実行が予期しない場所で起こり得る箇所を見つけるほうが、セキュリティ上の価値は相対的に高いと思います。
ただし、パッケージングエコシステム全体は、こうした承認プロセスについて検証されるべきだと思います。しかしそれは人間のプロセスに関するものなので、ソフトウェア監査というよりはレッドチーム型の監査に近いです。
“... These avenues do not necessarily violate Homebrew’s core security assumptions (which assume trustworthy formulae),...”
結果的には無害でしたが、人々がこうした Git リポジトリをそのままクローンして、うまく動くことを期待しているのは本当に怖いです。
TOB-BREW-n が複数並んでいるので、このプロジェクト専用の CVE 番号のようなものなのかと思いました。
追記: ああ、“Trail Of Bits - homeBREW” だったのですね。それでもたぶん合っているように思います。
TOB-$PRODUCT-$XXXXという慣例を使っています。$PRODUCTは監査対象で、$XXXXは各発見事項の一意な増分カウンターです。私の知る限り、多くの監査会社が似た方式を使っています。
このブログ記事の表現が少し紛らわしいです。Homebrew と一緒にこの監査を行ったとありますが、名前に見覚えがあったので Homebrew README を確認したところ、https://github.com/Homebrew/brew のメンテナー一覧に William Woodruff がいました。
ブログ記事でこの点に触れていない理由があるのか気になります。大きな違いを生むとは思いませんが、明確にしたいです。
長い間、このプロジェクトの非メンテナー「メンバー」でした。これは、内部の会話やガバナンスに引き続き参加したい元メンテナーに与えられる、準名誉職のような立場です。その後、監査が終わって数か月後、監査計画前には存在も予定もされていなかった Homebrew 関連の別作業がきっかけで、再びメンバーシップを提案されました。
この内容は、会社と Homebrew メンテナー双方に対して行った利益相反の開示にはすべて含めていましたが、ブログ記事にも明記できるという点には同意します。今日追加してみます。
要約すると、監査実施時点ではメンテナーではありませんでしたが、以前はメンテナーで、現在もメンテナーです。監査は私と同僚たちが専門業務として実施しました。