111日の沈黙を経て復活したnpmワーム「Shai-Hulud」、セキュリティスキャンをすり抜ける

既知のShai-Hulud型npmワームのペイロードが、111日間の沈黙を経て再び姿を現しました。レジストリレベルのマルウェア検査がどこまで機能しているのか、改めて疑問が投げかけられています。

Antivirus& Malware

5月のキャンペーンは、たった1件のメンテナーアカウントの侵害が、いかに早くソフトウェアサプライチェーンインシデントへと発展しうるかを示すものでした。

攻撃者は悪意あるバージョンをnpmパッケージ全体に配布しました。その対象には、広く利用されている可視化ライブラリやフロントエンド関連の依存パッケージも含まれていました。

このマルウェアはインストール時に実行され、開発者のワークステーションやCI/CDランナーから認証情報を窃取したうえで、盗んだnpm公開トークンを使って他のパッケージへと感染を広げていました。

今回新たに確認された活動が注目される理由は、新しい回避手法を導入しているからではなく、むしろ何も変わっていないように見える点にあります。

研究者らは、SHA-256ハッシュ値e37e3ddeeaaa9e0c4fdbcb829b4895a6521031c80053fc436625b61e6ee5b1a6から、この復活したペイロードを特定しました。これは以前@antvを巻き込んだ攻撃で確認されたものと同一のファイルです。

検出履歴によれば、このハッシュを持つパッケージバージョンは5月19日時点で319件確認されていましたが、その後は9月7日まで一切検出されず、実に111日間の空白期間があったとされています。

報告によると、このワームは同一のnpmアカウントから、同じ1時間以内にアップロードされた4つのパッケージを通じて再び公開されました。

[email protected][email protected][email protected]、そして[email protected]です。

関与したパッケージ数が限られているからといって、このインシデントを軽視すべきではありません。既知の悪性バイナリが3か月以上も変化しないまま再び出現したという事実は、レジストリのスキャン体制、脅威インテリジェンスの取り込み、パッケージ評価の仕組みといった基本的な防御機能が試された結果とも言えます。

特に懸念されるのは、npmが新規公開時にマルウェアスキャンを導入しており、パブリッシュされたパッケージが自動解析のために一時的にインストール不可の状態で保留される仕組みを備えていたはずだという点です。

Aikidoの研究者らによると、今回再活性化したパッケージが含んでいたペイロードは、5月19日に@antvエコシステムで数百のパッケージを侵害した事件と結び付けられていたものと、バイト単位で完全に一致していたとのことです。

111日を経て復活したnpmワーム

SHA-256ハッシュの完全一致は、マルウェア防御の中でも最も単純な検出手段の一つです。

疑わしいコードを実際に実行する必要も、難読化を解読する必要も、多段階の配送ロジックを解明する必要も、サンドボックスでペイロードの挙動を分析する必要もありません。

必要なのは、既知の悪性フィンガープリントとの照合だけです。今回のケースでは、このハッシュ値はすでに公にも分析され、大規模なサプライチェーン攻撃キャンペーンと結び付けられていました。

以前のMini Shai-Hulud攻撃では、preinstallのような悪意あるライフサイクルフックを利用し、npm install実行時にコードを動かす手口が使われていました。

侵害された@antvパッケージでは、注入されたローダーがbun run index.jsを使用しており、一部のリリースにはオプションのGitHub依存関係も含まれ、通常のnpmパッケージのペイロード以外にもう一つの実行経路が用意されていました。

実行されると、このマルウェアはGitHubおよびnpmのトークン、クラウド認証情報、SSHキー、Docker認証ファイル、Kubernetesサービスアカウントトークン、Vaultのシークレット、環境変数、データベース接続文字列などを探索していました。

Antivirus& Malware

さらにCI/CDインフラも標的とし、有効なGitHubトークンを取得した場合には、窃取したデータを保存するために攻撃者が管理するリポジトリを作成していました。

このキャンペーンが通常の認証情報窃取型マルウェアより格段に危険なのは、ワームとしての拡散機能を備えている点です。

盗まれたnpmの認証情報があれば、攻撃者はそのメンテナーが公開権限を持つパッケージを列挙し、パッケージアーカイブに悪意あるコードを注入したうえでバージョンを上げ、再公開することが可能になります。

つまり、侵害されたメンテナーアカウント一つひとつが、他のプロジェクトへの新たな感染拠点となりうるわけです。

公開時のスキャンには依然として一定の価値がありますが、今回の事案はその限界を浮き彫りにしました。

新規性が高く、暗号化され、多段階に仕込まれ、あるいは限定的な実行時条件下でしか起動しないマルウェアは、公開前に確実に分類するのが困難です。

しかし、公に文書化されている既知の悪性ハッシュと完全に一致するファイルについては、少なくとも基本条件としてブロックされるべきです。

より根深い問題は、ハッシュのみによるスキャンは、たとえ機能したとしても不十分だという点にあります。

攻撃者が1バイトでも変更し、アーカイブを再パッケージ化し、難読化を変え、あるいはペイロードをリモートの依存関係へと移動させれば、悪意ある機能を保ったまま新しいフィンガープリントを生成できてしまいます。

Shai-Huludの過去のキャンペーンでは、すでに難読化されたJavaScript、ライフサイクル実行、GitHubでホストされた「特殊な」依存関係を用いて攻撃対象範囲を広げる手口が確認されていました。

各組織は、ロックファイル、パッケージキャッシュ、ビルドログ、ソフトウェア部品表(SBOM)を直ちに確認し、今回新たに判明した4つのパッケージバージョンや、過去のShai-Hulud関連の痕跡が含まれていないかを点検すべきです。

該当バージョンをインストールしていたチームは、開発者エンドポイントやCIランナーが侵害された可能性があるものとして扱い、npmおよびGitHubのトークンをローテーションし、クラウドやデプロイ関連の認証情報を見直したうえで、不正なパッケージ公開活動がないか調査する必要があります。

セキュリティチームは、package.jsonの変更内容も確認し、想定外のライフサイクルスクリプト、特にpreinstallpostinstall、Bunや不明なシェルスクリプトを呼び出すコマンドがないかを点検すべきです。

過去のキャンペーンでは.vscode/tasks.json.claude/settings.jsonも改変されていたため、パッケージを削除するだけでは、侵害されたシステムに残された永続化機構を完全には排除できない可能性があります。

変化のないShai-Huludペイロードが再び出現したという事実は、サプライチェーンセキュリティを公開後の検出やレジストリ側の保証だけに委ねてはならないことを、改めて思い起こさせるものです。

ロックファイルによる依存関係の固定、メンテナートークンの権限範囲の制限、短命な認証情報の徹底、CIにおけるライフサイクルスクリプトの制限、そして新規公開バージョンの採用を意図的に遅らせることは、検出が追いつく前にワームが実行される機会を減らすうえで有効です。

侵害指標(IOC)

ネットワーク ファイル 永続化
t[.]m-kosche[.]com 5月のキャンペーンで確認されたコマンド&コントロール(C2)ドメイン。 SHA-256: e37e3ddeeaaa9e0c4fdbcb829b4895a6521031c80053fc436625b61e6ee5b1a6

ルート直下のindex.jsペイロード。

preinstallスクリプトがbun run index.jsを実行。

.vscode/tasks.jsonにより、攻撃者が制御するコマンドを実行するVisual Studio Codeタスクを設定可能。

.claude/settings.jsonにより、実行をサポートするためClaude Code/プロジェクト設定を変更可能。

注: IPアドレスおよびドメインは、誤った名前解決やハイパーリンク化を防ぐため、意図的に無害化表記(例: [.])としています。再度有効な形式に戻す作業は、MISP、VirusTotal、SIEMなど管理された脅威インテリジェンス基盤上でのみ行ってください。

7段階のメトリクス連動型AI SOC導入フェーズを解説 – 無料AI SOC導入プレイブック2026をダウンロード

翻訳元: https://gbhackers.com/npm-worm-returns-after-111-days/

本記事は gbhackers.com の記事を翻訳・要約したものです。