2021年3月28日、git.php.net上のphp-srcのmasterブランチに2つのコミットが現れ、PHPの創始者であるRasmus Lerdorfとコア開発者Nikita Popovの名前でプッシュされた。タイトルは「[skip-ci] Fix typo」——レビューを省略させるほど小さな主題であり、さらにskip-ci接頭辞によって継続的インテグレーションも回避するよう設計されていた。広くインクルードされるヘッダーへの変更は、サーバー変数のHTTP User-Agentを検査し、それが文字列「zerodium」で始まる場合、ヘッダーの残りをPHPコードとして実行するものだった。すなわち、汚染されたインタープリターを実行するあらゆるサーバー上でのリモートコード実行である。

これは機能しなかった。その理由は示唆に富む。コミットは数時間以内に、公開フィードを読んでいたコミュニティメンバーによって発見された——あるコメント投稿者がコミット自体でこの変更を指摘し、PHP開発者のJake Birchallがuser-agentヘッダーからコードが実行されることを確認した。Popovは同日夕方、すべては個々のアカウントではなくgit.php.netサーバーの侵害を指し示していると発表した。コミットのテキスト自体には「REMOVETHIS: sold to zerodium, mid 2017」という行があり、バックドアが数年前にエクスプロイトベンダーに仲介されていたことを示唆していた。

プロジェクトの対応は、資産を修復するのではなく除去することだった。git.php.netは即座に廃止され、それまで二次的だったGitHubミラーが正規リポジトリとなり、書き込みアクセスはメンバーシップに二要素認証を必須とするphp GitHub組織へ移され、さらなる改ざんがないかリポジトリを監査する間、すべてのPHPリリースが2週間保留された。2つのコミットは一人のエンドユーザーにも届かなかった。

エンドユーザーへの影響はなし——両方のコミットはリリース前に取り消された。実際の犠牲はプロジェクト自身のgitインフラと、すべてのPHPリリースの2週間の凍結だった。

プロジェクトは書き込みアクセスのために自作のカルマシステムを備えた独自のgitサーバーを運用していた——小規模なコアチームが完全に自前で防御しなければならない特注の認証面である。

そのサーバー上のコミットIDは暗号署名ではなくプッシュ時のサインオフに依存していたため、サーバーを制御する者は誰でもプロジェクトで最も信頼される名前でコミットできた。

偽装はレビュープロセスに合わせて調整されていた。ほぼどこにでもインクルードされるヘッダーにおける一語の「typo」修正で、CIを完全にスキップする接頭辞付きだった。

プロジェクトを救ったGitHubミラーは長年二流のコピーだった——チームが緊急時にそれらを昇格させることを選んだからこそ復旧できた。

バージョン管理のセルフホストは、プロジェクトに単独で防御しなければならない攻撃面以外の何ももたらさない。ミラーは、必要なその時間に信頼の源となれる準備ができている場合にのみ報われる。

php.netは調査が行われる間、リリースを正式に2週間保留し、悪意あるコミットは「直ちに発見され取り消されたため、エンドユーザーには決して届かなかった」と述べた。リポジトリは2つのコミット以外の改ざんがないかレビューされ、GitHubがphp-srcの恒久的な正規の拠点となり、組織のメンバーシップには現在2FAが必須となっている。バックドアのコードコメント——「sold to zerodium, mid 2017」——はコミット履歴に公開されたままである。ベンダーは購入を確認していない。

出典をたどる

出典

  1. Changes to Git commit workflow (php.internals #113838) news-web.php.net · news-web.php.net ·
  2. PHP releases on hold php.net · php.net ·
  3. [skip-ci] Fix typo (commit c730aa26) GitHub php/php-src · github.com ·
  4. PHP's Git server hacked to add backdoors to PHP source code BleepingComputer · bleepingcomputer.com ·