【ITニュース解説】Facing the Shai-Hulud Worm: Where the Hell is Easystreet?
2025年09月20日に「Dev.to」が公開したITニュース「Facing the Shai-Hulud Worm: Where the Hell is Easystreet?」について初心者にもわかりやすく解説しています。
ITニュース概要
NPMサプライチェーン攻撃「Shai-Hulud」は、フィッシングで開発者の認証情報を盗み、自己増殖マルウェアを含む不正パッケージを配布した。この攻撃から身を守るには、フィッシング対策、2要素認証、権限を絞ったトークン利用、定期的な鍵更新、そしてシステム全体のセキュリティ強化が不可欠である。
ITニュース解説
NPMエコシステムを標的とした「Shai-Hulud」と呼ばれるサプライチェーン攻撃が発生した。この攻撃は、JavaScript開発コミュニティが直面する多様なリスクを改めて認識させるものだ。Shai-Hulud攻撃は、単に情報を盗み出すだけの単純なものではなく、自己複製型のマルウェアを利用してNPMレジストリを通じて拡散し、複数の攻撃経路と脆弱性を巧妙に組み合わせた計画的なキャンペーンであった。システムエンジニアを目指す上で、このような脅威から自身の開発環境やプロジェクトを守る知識は不可欠である。
攻撃は、NPMパッケージのメンテナー(パッケージの管理や更新を行う開発者)を狙った標的型フィッシングから始まった。攻撃者は、本物のNPMセキュリティアラートを装った偽のメールを作成し、開発者からログイン情報(認証情報)をだまし取ろうとしたのだ。一度開発者のアカウントが侵害されると、攻撃者はそのアカウントを使って、広く使われているNPMパッケージに悪意のある更新版を公開することが可能となる。
このような攻撃を防ぐため、まず重要なのはフィッシングに対する意識向上だ。フィッシング詐欺の手口は常に進化しているため、その最新情報に常に注意を払い、訓練を続ける必要がある。特にNPMの重要な認証情報を守る立場にある場合は、メール内のリンクを安易にクリックしたり、個人情報を入力したりしない習慣を身につけることが極めて重要である。誰かを非難するのではなく、セキュリティを守るために個々人が意識を高めることが求められる。
アカウントへのアクセス権を得た攻撃者は、人気のあるNPMパッケージの悪意のあるバージョンをアップロードした。これらのパッケージには、インストール時に自動で実行され、自身を複製して拡散する「Shai-Huludワーム」というマルウェアが含まれていた。これに対する対策として、NPMでパッケージを公開する際には二段階認証(2FA)を必ず利用することが推奨される。開発現場では「mainブランチにプッシュしたらNPMに自動でデプロイ」といった運用もしばしば見られるが、このような利便性がセキュリティリスクを高める可能性があるため、追加の手間を惜しまず2FAを導入するべきだ。また、アジャイル開発やDevOpsにおける「1日200回デプロイ」のような高速化の概念が、セキュリティの考慮を後回しにしないよう注意が必要である。
悪意のあるJavaScriptコードに埋め込まれたBashスクリプトは、認証情報の窃盗、マルウェアの伝播、そしてシステム内での永続化を実現するためのルーチンを実行する。ここで巧妙なのは、認証情報をすぐに抜き取るのではなく、永続的にアクセスできる経路を確立することを優先する点だ。これには、リポジトリへのコミット(変更履歴の記録)が伴う。対策としては、コミットに電子署名を行うことで、誰が変更を行ったかを明確にし、不正なコミットを検出できるようにすることが考えられる。
GitHub ActionsのようなCI/CD(継続的インテグレーション/継続的デリバリー)パイプラインのセキュリティも重要だ。GitHub Actionsの設定ファイル(YAMLファイル)が保存されているフォルダには、ブランチ保護を設定し、特定のファイルやフォルダに対する変更には複数人のレビューや承認を必須とすることで、不正な変更を防ぐことができる。また、codeownersファイルを利用すれば、特定のコードや設定ファイルの変更を承認する担当者を指定できる。特に「actions」フォルダへの変更には人手による介入を義務付けるなど、厳重な管理体制を敷くべきである。
自動化されたツールからの認証情報窃盗を防ぐためには、パイプライン内でアプリケーションのテストやコード品質チェック(リンティング)などのタスクを実行する際に、Dockerコンテナのような隔離された環境を利用することが有効だ。これにより、誤って認証情報が外部に漏洩するリスクを低減できる。また、ビルド(アプリケーションの構築)とリリース(本番環境へのデプロイ)のパイプラインを分離し、それぞれのパイプラインが必要最小限の認証情報のみを使用するように設計することも重要である。開発者が自分の開発環境で何でもできる状態は便利だが、セキュリティの観点からはリスクとなる場合がある。
さらに、DockerコンテナのネットワークアクセスをDNS(ドメイン名システム)レベルで制限することも有効な対策の一つとして挙げられている。NPMからのパッケージインストールは単一のソースから行われるとしても、マルウェアによる情報抽出先が第三者のドメインである場合、その通信をブロックすることで攻撃を阻止できる可能性がある。すべてのトラフィックを制限し、許可された特定のドメインのみに通信を限定するDNSベースのプロキシの利用も検討できる。Dockerコンテナがインターネット接続を試みた際には、それを検知してアラートを発生させる仕組みも構築すべきだ。
OAuthスコープ(アクセストークンに付与される権限範囲)とトークン管理についても注意が必要である。残念ながら、クラウドネイティブなサービスでは「一つのトークンであらゆる領域にアクセス可能」という設定が頻繁に見られるが、これは大きなリスクとなる。GitHubのように、トークンに付与する権限をより細かく設定できるサービスを利用し、必要最小限の権限のみを付与する「最小権限の原則」を徹底すべきだ。特に多くの権限を持つトークンが必要な場合は、パイプラインをビルドと配布に分割し、それぞれの段階で必要な権限だけを持つトークンを使用するよう見直す必要がある。また、組織外のアカウントからの貢献は受け入れない方針も有効だ。トークンは静的な認証情報であるため、利用期間を制限し、定期的に更新(ロール)するプロセスを開発ライフサイクルの様々な段階で組み込むことが極めて重要となる。
鍵のロール(更新)は、セキュリティ対策の基本である。最初の本番デプロイが完了したら、関連する鍵をすべてロールし、再デプロイするべきだ。チームを去るメンバーがいた場合や、最悪の場合レイオフが発生した場合も、速やかにそのメンバーが使用していた鍵をすべてロールする。さらに、一定期間が経過したら鍵を自動的に無効化し、ロールするような仕組みも導入すべきである。依存関係のセキュリティ更新においては、もしサプライチェーンにおけるデータ流出が問題となった場合は、全ての変更履歴を確認するか、あるいは鍵が侵害されたと仮定してロールする。静的な鍵は可能な限り廃止し、自動化された鍵の取得とリセットプロセスを導入することで、鍵管理の手間を減らしつつセキュリティを向上できる。
攻撃者は、特定したプライベートリポジトリをすべてコピーし、完全な履歴付きでミラークローンを作成した。これらのクローンがユーザーのIDで公開されることは、DNSレベルでは解決できない深刻な問題だ。私たちはGitHubのようなコードホスティングサービスを信頼して利用しているが、コンテナや仮想マシン内でGitHubへの接続を制限することも検討できる。これは、最終的な情報抽出の迅速性を阻害するための一時的な対策に過ぎないかもしれない。なぜなら、この抽出方法が禁止されれば、攻撃者は別の方法を開発するだろうからだ。根本的な解決策ではないが、「侵害されている」という前提に立ち、包括的な「ゼロトラスト」の考え方を取り入れることが重要である。自身のコードベースが公開される可能性も考慮し、対応を検討する必要がある。
また、Webhook(Webサービス間の自動通信機能)を利用した認証情報の抽出にも警戒が必要だ。なぜ自身のパイプラインが、信頼できないドメインと通信することを許可しているのか、という問いを常に自らに投げかけるべきである。
JavaScriptとNPMの現状については、ある洞察が示されている。これは「専門化の罠」と呼ばれる問題に触れている。理論上は誰もが完璧なものを作れるかのように見えるが、CMS(コンテンツ管理システム)のようなツールは見た目をきれいにする一方で、表現を制限し、すべてを画一化してしまう。著者は、年を重ねるごとに「醜くてもより安全」な選択を重視するようになったと述べている。感染したリポジトリの初期ロードを分析したところ、多くの「なくても困らないが、あると便利なもの」(例えばターミナル用のANSIカラー表示機能など)が、他のモジュールに何度も組み込まれていることが判明したという。
そして、「時には、唯一の実行可能な行動は参加しないことだ」という「ウォー・ゲーム」からの引用で締めくくられている。これは、安易に多くの依存関係をプロジェクトに追加することへの警鐘であり、その必要性を深く問い直すことの重要性を示唆している。システムエンジニアとして、利便性だけでなく、セキュリティリスクと向き合い、賢明な選択をすることが求められている。