盗まれ流出した認証情報が原因で、AsyncAPIとJscrambler Code IntegrityのNode.jsパッケージがマルウェアに汚染されました。
開発者エコシステムを狙った攻撃は頻度と手口の両面で高度化が進んでおり、今週はNode.js開発者が標的の中心に据えられました。オープンソースのAsyncAPIおよびJscrambler Code Integrityに属する複数のnpmパッケージが、開発用認証情報の侵害を経てマルウェアに汚染されたのです。
今回の一連の事案は、盗まれた認証情報がさらなる侵害の実行に利用されるという、ソフトウェアサプライチェーン攻撃特有の連鎖的な影響を浮き彫りにしています。セキュリティ研究者は、汚染されたパッケージをインストールした開発者マシンについては、クリーンなイメージから完全に再構築するよう勧告しています。あわせて、npmトークン、ソースコントロールへのアクセス権、クラウド認証情報、CI/CDシークレット、SSH鍵、署名鍵、ブラウザセッションのすべてをローテーション(再発行)することを推奨しています。
影響を受けるパッケージは以下の通りです。[email protected]、[email protected]、[email protected]、[email protected]、[email protected]、@asyncapi/[email protected]、@asyncapi/[email protected]、@asyncapi/[email protected]、@asyncapi/[email protected]、および@asyncapi/[email protected]です。
ただし、上記の汚染されたパッケージを依存関係として指定しているパッケージも影響を受ける可能性があります。これには同一プロジェクトに属するjscrambler-webpack-plugin 8.6.2、gulp-jscrambler 8.6.2、grunt-jscrambler 8.5.2、jscrambler-metro-plugin 9.0.2なども含まれます。
侵入口として悪用された脆弱なGitHub Actionsワークフロー
イベント駆動アーキテクチャや非同期APIを実装するためのオープンソースのリファレンス仕様およびツールセットであるAsyncAPIに対する攻撃は火曜日に発生し、npmレジストリを監視するUpwind、Socket.dev、Wiz、StepSecurity、Aikido Securityなど複数のセキュリティ企業がそれぞれ独自に検知しました。
研究者らの分析によると、攻撃者は4月に報告されていたGitHub Actions CI/CDワークフローの既知の設定不備を悪用しました。この不備はpull_request_targetイベントに関するもので、このイベントは新規プルリクエストが作成されるたびに実行されます。トリガーされると、ワークフローは開発者から提出されたプルリクエストのコードをActionsコンテナ内で自動的にチェックアウトして実行しますが、この処理はベースリポジトリのコンテキストで行われ、シークレットへの完全なアクセス権を伴います。
AsyncAPIプロジェクトでは5月17日以降修正案が提出されていたものの、正式なレビューを経ておらず、メインブランチにはまだマージされていませんでした。
Wizの研究者らはレポートの中で次のように説明しています。「協定世界時05:08、攻撃者は約1,000バイトの空白の後に難読化されたJavaScriptを隠し込んだMarkdownファイルを含むPR #2155を作成しました。このペイロードは、GitHub Actionsランナーの環境内をスキャンしてシークレットを探し出し、rentry.coのペーストビン上にあるデッドドロップURLへ外部送信するよう設計されていました」。
GitHub Actionsのワークフローがトリガーされて環境内で実行されると、リポジトリに対して認証済みのgitコマンドを実行できるよう、一時的なGITHUB_TOKENが生成されます。他のトークンが含まれる場合もあります。
今回のケースでは、攻撃者はasyncapi-botに紐づくトークンの取得に成功しました。これはGitHub上のAsyncAPI組織全体にアクセス権を持つサービスアカウントです。これにより攻撃者は、2つの別々のリポジトリで悪意あるコードのコミットを実行できるようになりました。これらのコミットが自動ビルドワークフローを起動し、npmパッケージが生成・公開される結果となりました。
パッケージに組み込まれていたペイロードは、過去のサプライチェーン侵害で使用されたMiasmaと呼ばれるマルウェアフレームワークといくつかの類似点を持っています。ただし、マルウェアのコード自体は、これまでに確認されている亜種とは大きく異なっているようです。
第1段階のコードは、Linux、Windows、macOS向けにそれぞれ亜種を持つ第2段階のトロイの木馬型ペイロードをダウンロードします。これは認証情報窃取機能を備えたモジュール式マルウェアフレームワークで、ブラウザに保存されたパスワードやCookie、SSH鍵、npmおよびGitHubのトークン、AWS認証情報、macOSのキーチェーン、暗号資産ウォレットを標的にします。
このトロイの木馬はコマンド&コントロールサーバーと通信し、リモートからのコマンドを受け取ってファイル操作、ディレクトリの一覧取得、データの外部送信を実行できます。
流出したnpm認証情報を通じて侵害されたJscrambler
Jscramblerに対する攻撃は7月11日の週末に発生し、攻撃者は2波にわたって複数のトロイの木馬化バージョンを公開しました。Jscrambler Code Integrityは、JavaScriptベースのウェブアプリおよびモバイルアプリを改ざんやリバースエンジニアリングから保護するために設計されたクライアントサイドのセキュリティライブラリです。
Jscramblerは今回の事案を受けてアドバイザリを公開し、攻撃者がnpmの公開用認証情報を使って悪意あるバージョンを公開したことを明らかにしました。ただし、AsyncAPIのケースとは異なり、その認証情報がそもそもどのように流出したのかは明らかになっていません。
攻撃者は当初、設定スクリプト内のpreinstallフックを利用してインストール時に実行される2つの悪意あるスクリプトを組み込んだ新バージョンのパッケージを公開しました。これらのスクリプトは、難読化されたコンテナに埋め込まれたLinux、macOS、Windows向けのプラットフォーム別バイナリも実行します。
preinstallやpostinstallのフックはnpmパッケージでマルウェアを配布する際によく使われる手口であるため、セキュリティツールによって自動的にチェックされます。検知を回避するため、攻撃者は手法を切り替え、悪意あるコードをdist/index.jsとdist/bin/jscrambler.jsのファイルに直接注入するようにしました。これにより、マルウェアが実行されるタイミングは、パッケージのインストール時から、パッケージが他のプロジェクトにインポートされた時、あるいはJscrambler CLIが呼び出された時へと変化しました。
異なるプラットフォーム向けに埋め込まれたマルウェアの実行ファイルはRustで書かれており、Socket.devの分析によれば、「開発者を標的とした広範な認証情報・シークレット窃取ツール」であり、ブラウザ拡張機能の暗号資産ウォレット、AIコーディングアシスタントやMCPサーバーのAPIキー、AWS・Azure・GCPのクラウド認証情報、Discord・Slack・Telegramといったメッセージングアプリの認証トークン、ブラウザやSteam、KDEのパスワードストアなどを標的にしていたとのことです。