Transcript
00:00:00シャイ・フルドが4度目の続編で帰ってきました。
00:00:02今回はTanStackといったパッケージを狙っています。
00:00:04私がNext.jsの動画を公開した数時間後のことです。
00:00:07我ながら絶妙なタイミングでした。
00:00:08これは大規模なNPMサプライチェーン攻撃で、
00:00:11TanStack以上の影響を与えています。
00:00:13UiPathやMistralといったパッケージも含まれ、
00:00:15その他160ものパッケージが標的となりました。
00:00:17Guardrails.aiのようなPyPIパッケージすら含まれています。
00:00:20さらに面白いのは、
00:00:22デッドマン・スイッチが組み込まれている点で、
00:00:24盗まれたキーをローテーションしたと検知されると、
00:00:26PC全体をワイプしてしまうんです。
00:00:28世界情勢を反映した要素まで盛り込まれていました。
00:00:30では、深掘りしていきましょう。
00:00:36この続編で「ワーム」の目的は同じです。
00:00:39開発者のマシンやCI/CDランナーから認証情報を盗み、
00:00:42その情報を使ってさらに別のパッケージへ侵入することです。
00:00:44TanStackの場合、42個のパッケージで84もの
00:00:47悪意あるバージョンがわずか数分で公開されました。
00:00:51彼らがどのようにして
00:00:52TanStackに感染させたのかを解説しますが、
00:00:54まずは、これらのパッケージをインストールすると
00:00:56マルウェアが何をするのかを見てみましょう。
00:00:58悪意あるパッケージの内部には、
00:00:59「routerinit.js」という新しいファイルと、
00:01:02注入されたオプションの依存関係が見つかります。
00:01:04それは一見、
00:01:05正規のTanStack RouterのGitHubリンクのようですが、
00:01:08実際は攻撃者のフォークにある迷子のコミットです。
00:01:10GitHubのフォークリンクの仕様を利用しており、
00:01:13URLだけ見ると
00:01:14オリジナルのプロジェクトのものに見えますが、
00:01:16実際はフォーク先からのコミットなのです。
00:01:18そのフォークにはライフサイクルスクリプトの
00:01:20「prepare」があり、bunでタスクランナーを実行し、
00:01:22最後で「exit 1」を呼び出します。
00:01:24これはペイロードを実行した後に
00:01:27あえてオプションの依存関係を失敗させ、
00:01:28インストール処理を通常通り継続させて、
00:01:30ログに痕跡を残さないようにするための巧妙な手口です。
00:01:33お気づきかもしれませんが、
00:01:35冒頭で言及した「routerinit.js」が動いているわけではありません。
00:01:37しかし今は、この2つのファイルは
00:01:38名前が違うだけで全く同じ役割を果たすと
00:01:40考えておいてください。
00:01:42要約すると、これをインストールすると
00:01:44スクリプトが実行されます。
00:01:46最初の処理は、
00:01:47インストールフローから自身を切り離すことです。
00:01:50すでにバックグラウンドで実行中かどうかを確認し、
00:01:51そうでなければ、
00:01:53自身のコピーを切り離してフォークし、
00:01:54親スクリプトは正常終了します。
00:01:57これにより、npmのインストールログには
00:01:58スクリプトの出力が一切残りません。
00:02:00マルウェアは実行プロセスから切り離され、
00:02:01バックグラウンドで動いているからです。
00:02:04その後、非常に賢いことをします。
00:02:06自身のコピーを
00:02:07Claude Codeのフックディレクトリに書き込み、
00:02:08そのプロジェクトでClaude Codeを使うたびに
00:02:10フックが実行されるよう設定します。
00:02:12これでインストール後も存続し、
00:02:13プロジェクトでClaude Codeを開くたびに
00:02:16再起動するようになります。
00:02:17実際、VS Codeのタスクランナーでも同じことを行い、
00:02:20自分自身を複製します。
00:02:22そのため、VS Codeのワークスペースの
00:02:23自動実行機能を使っている場合も同じ問題が発生します。
00:02:26さらに「GitHub Token Monitor」という
00:02:28OSレベルのサービスまで設定します。
00:02:29これについては後ほど触れます。
00:02:31本当に悪魔のような代物ですから。
00:02:32まだチャンネル登録していないのも悪魔的ですね。
00:02:34さて、ペイロードが次にやるのは、
00:02:35認証情報の窃盗です。
00:02:37あらゆる場所を探し回ります。
00:02:38GitHub Actionsでは環境内から資格情報や
00:02:40シークレットを探します。
00:02:41具体的には、GitHub Actionsランナーの
00:02:43ワーカプロセスからメモリをスクレイピングして、
00:02:45マスクされたシークレットを含む
00:02:47ワークフローの秘密情報を抜き出します。
00:02:48さらに、CodeQLを装った偽のワークフローを挿入し、
00:02:50リポジトリの秘密情報をシリアライズして
00:02:52さらに、CodeQLを装った偽のGitHubワークフローを挿入し、
00:02:55AWSのシークレットも狙います。
00:02:57最初は環境変数やローカルの設定ファイルですが、
00:02:58IMDSv2やECSタスクメタデータといった
00:03:00AWSメタデータサービスまで攻撃します。
00:03:02Kubernetesでは、サービスアカウントのトークンや
00:03:03証明書を盗みます。
00:03:06これにより、そのポッドが持つ権限で
00:03:09クラスター内APIにアクセスできます。
00:03:11設定が甘いクラスターなら、実質管理者権限を
00:03:14奪取されたも同然です。
00:03:17さらに悪いことに、HashiCorp Vaultまで標的です。
00:03:19Vaultに関連する環境変数やトークンを収集し、
00:03:21手に入れたKubernetesアクセス権を使って
00:03:22Vault管理下のすべてのシークレットを取得します。
00:03:24これらはすべて、
00:03:25さらに悪いことに、HashiCorp Vaultも標的にし、
00:03:27ワークステーション上であれば、
00:03:29SSHキー、
00:03:30NPM資格情報、Git資格情報、
00:03:32シェルの履歴、クラウドプロバイダーの認証情報、
00:03:34仮想通貨のキー、
00:03:35Signal、Slack、Discordのファイルまで。
00:03:37さらに追い打ちをかけるように、
00:03:38Claude Codeのセッション履歴まで抽出します。
00:03:39もしあなたがClaudeに資格情報を与えたり、
00:03:41資格情報が含まれるファイルを読み込ませていたら、
00:03:42それらにもアクセスされます。
00:03:43そう、彼らは手に入れられるものなら
00:03:44何でも狙っているのです。
00:03:45そしてそのデータは、
00:03:45Sessionメッセンジャーネットワークを通じて
00:03:45外部へ送られます。
00:03:46バックアップとして、
00:03:47GitHubリポジトリにも盗んだデータを死蔵します。
00:03:49攻撃のテーマに合わせ、
00:03:51ブランチ名は『デューン』にちなんだものです。
00:03:53資格情報が盗まれた。これ以上悪くなるはずがない?
00:03:55いいえ、もっと悪くなります。
00:03:56先ほど話したマシン上に設定されたサービスですが、
00:03:57あれはGitHubトークンを監視し、
00:03:58何度も再流出させます。
00:04:00それだけではありません。
00:04:021分ごとにトークンが有効か確認し、
00:04:02無効であればユーザーディレクトリに
00:04:04GitHubのリポジトリに流し込みます。
00:04:05そして彼らの攻撃のテーマに合わせて、
00:04:07これらのブランチは『デューン』にちなんで命名されています。
00:04:09認証情報も盗まれました。
00:04:11これ以上悪くなることはないですよね?
00:04:12ところが、
00:04:13悪くなるんです。
00:04:14それだけでなく、
00:04:15先ほど言った
00:04:16PC内にセットアップされるサービスですが、
00:04:18あれがGitHubトークンを監視していて、
00:04:19本当にとんでもなく悪質です。
00:04:21補足として、
00:04:22この攻撃のPython版もほぼ同様ですが、
00:04:24マシンの言語がロシア語かどうかを確認します。
00:04:25もしそうなら、ただ停止するのです。
00:04:27イスラエルかイランのマシンと見なされると、
00:04:281から6の乱数を生成し、
00:04:30もし「2」が出ると、
00:04:31破壊的なワイプコマンドを実行し、
00:04:32MP3ファイルを最大音量で再生しようとします。
00:04:33残念ながら、
00:04:35そのMP3が何なのかは分かりませんでした。
00:04:36とにかく、ここまでの処理が終わったら、
00:04:38本当の地獄はこれからです。
00:04:39これはまだステージ1に過ぎません。
00:04:40ステージ2は自己増殖であり、
00:04:42これがこの攻撃の最も危険な部分です。
00:04:44まずマシン上で、
00:04:462要素認証なしでパッケージを公開できる
00:04:47有効なNPMトークンを探します。
00:04:48見つかれば、
00:04:49そのアカウントがアクセス可能な
00:04:51すべてのパッケージをスキャンし、
00:04:53資格情報を使って
00:04:53自分自身をそのパッケージに追加し、
00:04:54新たな感染バージョンを公開します。
00:04:55これは明らかに大問題ですが、
00:04:56そもそも2要素認証をバイパスできるトークンを
00:04:58放置しておくべきではありません。
00:04:59ですが、より恐ろしいのは、
00:05:00これがCI/CD環境内で実行された場合です。
00:05:01CI環境において、攻撃者は
00:05:03永続的なNPMトークンを必要としません。
00:05:04優れた設定であれば
00:05:05OIDCに依存しているからです。
00:05:05そのMP3が何かは分かりませんでした。
00:05:07とにかく、
00:05:07それが終わると、
00:05:08最悪なのはこれからです。
00:05:09まだ第1段階に過ぎませんから。
00:05:11第2段階は自己増殖です。
00:05:13これがこの攻撃において
00:05:15最も危険な部分です。
00:05:16まず、
00:05:16マシン内を検索し、
00:05:17有効なNPMトークンを探します。
00:05:19二要素認証なしで
00:05:19公開できるものを探すのです。
00:05:21もし見つかれば、
00:05:22そのアカウントがアクセス可能な
00:05:24全パッケージをスキャンし、
00:05:26認証情報を使って
00:05:26自分自身をパッケージに加え、
00:05:28感染した新しいバージョンを公開します。
00:05:30これは明らかに非常に悪質ですが、
00:05:32そもそも二要素認証を
00:05:33回避できてしまう
00:05:33トークンを
00:05:34バイパスできてしまう
00:05:35二要素認証を
00:05:36さらに恐ろしいのは
00:05:38これが
00:05:39CI/CD内で実行された場合です。
00:05:41CI環境では
00:05:42攻撃者は
00:05:43長期的なNPMトークンを
00:05:44必要としません。
00:05:45優れた構成では多くの場合
00:05:47より安全とされるOIDCを
00:05:48利用するからです。
00:05:49基本的には
00:05:50NPMトークンをシークレットとして保存せず
00:05:51GitHub ActionsがNPMに対して
00:05:53「ねえ、
00:05:53私はこのリポジトリで
00:05:54このワークフローを実行している」
00:05:55と証明すると
00:05:56NPMがその都度
00:05:57短期的な公開トークンを発行します。
00:05:59しかし問題は
00:06:00スクリプトがアクセス権を得て
00:06:01信頼されたGitHub Actions環境に入り込むと
00:06:03正規の公開者と同じ位置に
00:06:04なりすませるということです。
00:06:06そのためマルウェアは
00:06:07GitHubがジョブに公開している
00:06:08OIDC関連環境を利用し
00:06:10GitHubのトークンエンドポイントから
00:06:12OIDC JWTトークンを要求します。
00:06:14さらにそのJWTトークンを
00:06:16NPMと交換し
00:06:17短期的な公開用トークンを
00:06:18NPMの信頼された
00:06:19公開システムを通じて取得します。
00:06:20こうして恒久的なトークンを
00:06:22盗むことなく
00:06:22完全に正規の手順に見せかけて
00:06:24パッケージを公開できるのです。
00:06:26今回の場合
00:06:26マルウェアは例の
00:06:27router init.jsファイルのコピーを
00:06:29パッケージのテーブルに組み込み
00:06:30悪意のある
00:06:31オプションの依存関係を追加し
00:06:32最新タグとして
00:06:33すべて公開しました。
00:06:34そのため誰かが
00:06:35あるいはCI/CDパイプラインが
00:06:35そのパッケージをインストールすると
00:06:37またループが始まり
00:06:38可能な限りどこまでも
00:06:40拡散していくのです。
00:06:40かなり恐ろしいですよね?
00:06:42さて、では
00:06:42「ペイシェント・ゼロ(感染源)」となった
00:06:43TanStackに注目してみましょう。
00:06:44そもそも
00:06:46彼らはどうやって感染したのでしょうか?
00:06:46彼らの事後報告によると
00:06:47攻撃者は
00:06:48GitHub Actionsのパイプラインを悪用しました。
00:06:49悪意のあるパッケージが公開される前日
00:06:50攻撃者はTanStack routerのフォークを作成しましたが
00:06:51それを「configuration」という名前に変更し
00:06:53フォーク一覧から探しにくくしました。
00:06:53そしてそのフォークに
00:06:54悪意のあるコミットを追加しました。
00:06:56作成者は偽の「Claude」名義で
00:06:57TanStack routerをフォークし
00:06:58「skip CI」という接頭辞を付け
00:06:59プッシュイベントで
00:06:59すぐにCIが走らないようにしていました。
00:07:01翌日
00:07:02TanStack routerに対して
00:07:04「Work in Progress Simplify History Build」
00:07:04というPRを作成しました。
00:07:05ここで実際の攻撃が行われます。
00:07:06要点はこうです。
00:07:07TanStackは
00:07:07bundle-sizedという
00:07:08GitHub Actionsワークフローを持っていて
00:07:09pull_request_targetを
00:07:10使用していました。
00:07:11これが注目すべき点なのは
00:07:13pull_request_targetは
00:07:13フォークではなく
00:07:14TanStack Routerに対し
00:07:15Work in Progress
00:07:16Simplify History Buildと題した
00:07:18PRを開きました
00:07:18ここが実際の攻撃の
00:07:20発端となります
00:07:21TanStackにはバンドルサイズの
00:07:22GitHub Actionsワークフローがあり
00:07:23ベンチマークビルドを実行しました。
00:07:25しかし問題は、そのフォークに
00:07:26悪意のあるコードが含まれていたことです。
00:07:27今回のケースでは
00:07:28PMPMパッケージストアを毒する
00:07:29セットアップスクリプトが含まれており
00:07:30リリースアクションが
00:07:31後に使用する
00:07:32正確なキャッシュキーで毒されました。
00:07:33そしてGitHubトークンにもアクセスできます。
00:07:35PMPMロックファイルから
00:07:35ワークフローと同じ計算式を使って
00:07:36このキャッシュキーを事前計算していました。
00:07:38毒されたキャッシュが保存されると
00:07:39彼らはそのブランチを
00:07:40現在のメインブランチと一致するように
00:07:40リセットし
00:07:41外からは
00:07:42何も変更がないように見える
00:07:43PRにして
00:07:44PRを閉じ
00:07:45悪意のあるブランチを削除しました。
00:07:47外から見ると
00:07:48何も起きていないように見えますが
00:07:49GitHub Actionsのキャッシュは
00:07:50既に毒されているのです。
00:07:51つまり8時間後に
00:07:52通常のメンテナが
00:07:54関係のないPRをメインにマージした際に
00:07:56TanStackの
00:07:57リリースワークフローがトリガーされ
00:07:57毒されたPMPMキャッシュが復元され
00:07:58攻撃者がコントロールするコードが
00:07:59リリースアクション内で
00:07:59実行されてしまったのです。
00:08:00あとは先ほどと同じく
00:08:01OIDCを使って
00:08:02NPM公開トークンを取得し
00:08:0342個のTanStackパッケージにわたり
00:08:0484もの
00:08:05自身(マルウェア)のバージョンを
00:08:06公開してしまいました。
00:08:07しかも驚くことに
00:08:07アクション自体は
00:08:08テストの失敗で落ちたため
00:08:09本来の公開ステップには
00:08:10GitHub Actionsのキャッシュが汚染されてしまうのです。
00:08:11悪意のあるコードは
00:08:12その前に実行され
00:08:13すべてが公開されてしまいました。
00:08:14攻撃者は3つの信頼境界を
00:08:15連鎖させたことになります。
00:08:161つ目は
00:08:17フォークPRのコードで
00:08:18ベースリポジトリのキャッシュを毒し
00:08:192つ目は
00:08:20その毒されたキャッシュが
00:08:22実際のリリースワークフローで復元され
00:08:233つ目は
00:08:24そのワークフローが持つOIDC権限が
00:08:25NPM公開権限へと変換されたことです。
00:08:26おかげで完全に正規のものに見える
00:08:28パッケージを公開できたのです。
00:08:29これが、サプライチェーン攻撃において
00:08:30私が本当に恐ろしいと考えている部分です。
00:08:32攻撃者はメンテナのトークンを
00:08:33盗むことから
00:08:34CI/CDシステム全体を
00:08:35悪用することに
00:08:36シフトしています。
00:08:36それはつまり
00:08:37我々の持つ「信頼のシグナル」が
00:08:39攻撃者のために働き始めている
00:08:40ということです。
00:08:41これは正規のワークフローによって公開された
00:08:43妥当な証明を持つ
00:08:43署名済みパッケージでした。
00:08:44さて、これが「ShaiHalud4」の正体です。
00:08:46もしあなたが
00:08:47これらのパッケージによって
00:08:47侵害されていないか確認したい場合は
00:08:48下のリンクから
00:08:49ブログ記事を参照してください。
00:08:51確認方法や
00:08:52インストールしてしまった場合の対処法が
00:08:53書かれています。
00:08:54NPMエコシステムの
00:08:56この件についてどう思うか
00:08:57コメントで教えてください。
00:08:58よろしければ
00:08:59チャンネル登録もお願いします。
00:08:59それではまた次回
00:09:01お会いしましょう。
00:09:02非常に恐ろしいことだと
00:09:03思っています
00:09:05サプライチェーン攻撃は
00:09:05今や
00:09:06管理者のトークンを盗む段階から
00:09:07システムそのものを
00:09:08悪用する段階へと移行しています
00:09:10つまり
00:09:11私たちが頼りにしている
00:09:12信頼の証そのものが
00:09:13攻撃者のために
00:09:14機能し始めているのです
00:09:15これは署名済みのパッケージであり
00:09:16正当なプロベナンスも備え
00:09:18正式なワークフローで
00:09:19公開されたものでした
00:09:20以上が
00:09:21ShaiHalud4についてです
00:09:21もし被害に遭っていないか
00:09:23確認したい場合は
00:09:23下のリンクから
00:09:25ブログ記事を見てください
00:09:25そのパッケージを確認する方法や
00:09:26万が一インストールしていた場合の
00:09:27対処法が
00:09:28記載されています
00:09:29今回の件や
00:09:30NPMエコシステムについて
00:09:30どう思われたか
00:09:31ぜひコメントで教えてください
00:09:33ついでに
00:09:33チャンネル登録も
00:09:34よろしくお願いします
00:09:34ではまた次回
Community Posts
No posts yet. Be the first to write about this video!
Write about this video