Elastic Security Labsは、Axiosのサプライチェーン侵害に関する初期トリアージおよび検出ルールを公開した。これはRATとペイロードの詳細な分析です。
はじめに
Elastic Security Labsは、JavaScriptエコシステムで最も依存されているパッケージの1つであり、毎週約 100 百万回ダウンロードされているaxios npmパッケージのサプライチェーン侵害を特定しました。攻撃者は管理者アカウントを侵害し、バックドアを仕込んだバージョンを公開した。このバージョンは、悪意のあるインストール後フックを介して、macOS、Windows、Linuxシステムにクロスプラットフォームのリモートアクセス型トロイの木馬を配信した。
重要なポイント
- 侵害されたnpmメンテナーアカウント(jasonsaayman)が、広く使用されているAxios HTTPクライアントの悪意のある2つのバージョン(1.14.1(latestタグ付き)と0.30.4(legacyタグ付き))を公開するために使用され、デフォルトのnpm install axiosがバックドア付きのパッケージに解決されることになった。
- この悪意のあるJavaScriptは、macOS、Windows、Linux向けにプラットフォーム固有のステージ2インプラントを展開します。
- ステージ2の3つのペイロードはすべて、同一のRAT (リモートアクセス型トロイの木馬)の実装であり、同一のC2プロトコル、コマンドセット、ビーコンの送信頻度、および偽装されたユーザーエージェントを備え、PowerShell(Windows)、C++(macOS)、およびPython(Linux)で記述されている。
- ドロッパーは、自身を削除し、パッケージ.jsonをクリーンなコピーと置き換えることで、フォレンジック対策のクリーンアップを実行し、インストール後のトリガーの証拠を消去します。
node_modules
前文
30 、 2026 3 月、Elastic Security Labs は、自動サプライチェーン監視により、 axios npm パッケージを標的としたサプライチェーン侵害を検出しました。攻撃者は、プロジェクトの主要なメンテナーの一人であるjasonsaaymanのnpmアカウントを乗っ取り、39分以内にバックドアを仕込んだ2つのバージョンを公開した。
axiosパッケージは、JavaScriptエコシステムにおいて最も広く利用されているHTTPクライアントライブラリの一つです。発見当時、最新版と旧版の両方の配布タグが脆弱性のあるバージョンを指しており、新規インストールの大部分がバックドア付きのリリースをダウンロードしていたことが判明した。
悪意のあるバージョンは、plain-crypto-js という専用のパッケージという単一の新しい依存関係を導入しました。このパッケージの postinstall フックは、sfrclak[.]com:8000 からプラットフォーム固有のステージ 2 RAT インプラントを静かにダウンロードして実行します。
この作戦を爆発範囲以上に注目すべきものにしているのは、第2段階の兵器システムである。攻撃者は、Windows、macOS、Linux向けにそれぞれ1つずつ、同じRATの3つの並行実装を展開した。これらはすべて、同一のC2プロトコル、コマンド構造、およびビーコン動作を共有していた。これは3つの異なるツールではなく、プラットフォームネイティブな実装を備えた単一のクロスプラットフォームインプラントフレームワークです。
Elastic Security Labs は、情報開示を調整し、メンテナーと npm レジストリが侵害されたバージョンに対応できるようにするために、 3 月 31 日午前 2026 01 50分 (UTC) にaxios リポジトリに対して GitHub セキュリティ アドバイザリを提出しました。
コミュニティがソーシャルメディア上でこの脆弱性を指摘したことを受け、Elastic Security Labsは防御側がリアルタイムで対応できるよう、初期調査結果を公表した。
この記事では、npmレベルのサプライチェーン侵害から難読化されたドロッパー、クロスプラットフォームRATのアーキテクチャ、そしてその3つの亜種間の重要な違いまで、攻撃チェーン全体を網羅的に解説します。
キャンペーン概要
その妥協は、npmレジストリのメタデータから明らかである。メンテナーのメールアドレスは、以前の正規リリースではすべて存在していたjasonsaayman@gmail[.]comから、悪意のあるバージョンではifstap@proton[.]meに変更されました。出版方法も変更された。
| バージョン | 発行元 | Method | 由来 |
|---|---|---|---|
axios@1.14.0 (正当な) | jasonsaayman@gmail[.]com | GitHub Actions OIDC | SLSAの出所証明 |
axios@1.14.1 (侵害された) | ifstap@proton[.]me | 直接CLI公開 | なし |
axios@0.30.4 (侵害された) | ifstap@proton[.]me | 直接CLI公開 | なし |
SLSAの来歴情報を持つ信頼できるOIDCパブリッシャーフローから、変更されたメールアドレスを使用した直接CLIパブリッシュへの移行は、不正アクセスがあったことを明確に示しています。
タイムライン
- 2026-02-18 17 : 19 UTC —
axios@0.30.3はjasonsaayman@gmail[.]comによって正当に公開されました - 2026-03-27 19 : 01 UTC —
axios@1.14.0GitHub Actions OIDC を通じて正当に公開されました - 2026-03-30 05 : 57 UTC —
plain-crypto-js@4.2.0はnrwise(nrwise@proton.me) によって公開されました — レジストリ履歴を構築するためのクリーンなデコイ - 2026-03-30 23 : 59 UTC —
plain-crypto-js@4.2.1はnrwiseによって公開されました —postinstallバックドア付きの悪意のあるバージョン - 2026-03-31 00 : 21 UTC —
axios@1.14.1侵害されたアカウントによって公開 — タグ付け済みlatest - 2026-03-31 01 : 00 UTC —
axios@0.30.4侵害されたアカウントによって公開 — タグ付け済みlegacy
影響を受けるパッケージ
axios@1.14.1— 悪意のある行為、発見時にlatestとタグ付けaxios@0.30.4— 悪意のある行為、発見時にlegacyとタグ付けplain-crypto-js@4.2.0— クリーンな囮、登録履歴を構築するために公開plain-crypto-js@4.2.1— 悪意のあるペイロード配信車両(postinstallバックドア)
安全なバージョン: axios@1.14.0 (SLSA 由来を持つ最後の正規 1.x リリース)およびaxios@0.30.3 (最後の正規0.30.xリリース)。
攻撃者は最新チャンネルと旧チャンネルの両方にタグを付け、現行または旧バージョンのaxios APIを使用しているプロジェクト全体に影響範囲を最大化しました。
コード分析
ステージ1:プレーンな暗号化JSドロッパー
配信チェーン全体は、npmのpostinstallライフサイクルフックに依存している。改ざんされたaxiosバージョンをインストールすると、依存関係としてplain-crypto-js@^4.2.1が引き込まれ、以下のように宣言されます。
"scripts": {
"postinstall": "node setup.js"
}
これにより、npm install の実行中に setup.js が自動的に実行されるようになり、ユーザーによる操作は不要になります。
setup.jsファイルは、その動作を隠蔽するために2層エンコーディング方式を使用しています。
- レイヤー1:文字列反転とそれに続くBase64デコード
- レイヤー2:位置依存インデックス(7 * i² % 10)を使用した鍵OrDeR_7077によるXOR暗号
重要な文字列、モジュール名、URL、シェルコマンドはすべてエンコードされた配列stq[]に格納され、実行時にデコードされます。解読された内容から、運用インフラが明らかになった。
プラットフォーム固有の配信
ドロッパーは文字列テーブルをデコードした後、os.platform() をチェックし、3 つの配信ルーチンのいずれかに分岐します。それぞれがプラットフォーム固有のボディ(packages.npm.org/product0)を含むHTTP POSTリクエストをhttp://sfrclak[.]com:8000/6202033に送信します。(macOS)、packages.npm.org/product1(Windows)、packages.npm.org/product2(Linux)— C2が単一のエンドポイントから正しいペイロードを提供できるようにする。packages.npm.org/プレフィックスは、ネットワークログ上で送信トラフィックを無害なnpmレジストリ通信として表示させるための意図的な試みです。
| Elastic Platform | 配送方法 | ステージ2の場所 | 変装 |
|---|---|---|---|
| macOS | AppleScript は osascript を介して curl でバイナリをダウンロードします | /Library/Caches/com.apple.act.mond | Appleシステムデーモン |
| Windows | VBScriptのダウンロード .ps1curl を介して実行され、名前が変更された PowerShell ( %PROGRAMDATA%\wt.exe ) を介して実行されます | %TEMP%\6202033.ps1 (一時的な) | Windowsターミナル |
| Linux | curlによる直接ダウンロードとPython3による実行 | /tmp/ld.py | なし |
反鑑識
ドロッパーは、次の2つのクリーンアップ処理を実行します。
- 自己削除: setup.js は fs.unlink(__filename) を介して自身を削除します。
- パッケージマニフェストの交換: package.md という名前のクリーンなファイル (インストール後のフックのない無害なバージョン 4.2.0 構成を含む) が package.json に名前変更されます。悪意のあるバージョンを上書きする
インシデント発生後のnode_modules/plain-crypto-js/package.jsonの調査では、postinstallトリガーの痕跡は見つかりませんでした。悪意のあるsetup.jsファイルは削除されました。証拠が残るのは、ロックファイルとnpmの監査ログのみです。
ステージ2:クロスプラットフォームRAT
ステージ2の3つのペイロード、すなわちWindows用のPowerShell、macOS用のコンパイル済みC++、Linux用のPythonは、3つの異なるツールではありません。これらは同一のRAT仕様の3つの実装であり、同一のC2プロトコル、コマンドセット、メッセージフォーマット、および動作特性を共有している。その一貫性は、単一の開発者、あるいは共有設計文書に基づいて作業する緊密に連携したチームの存在を強く示唆している。
共有アーキテクチャ
以下の特性は、 3つのバリアントすべてに共通しています。
- C2トランスポート: HTTP POST
- ボディのエンコード: Base64エンコードされたJSON
- ユーザーエージェント:
mozilla/4.0 (compatible; msie 8.0; windows nt 5.1; trident/4.0) - ビーコン間隔: 60 秒
- セッションUID:実行ごとに生成される16文字のランダムな英数字文字列
- 送信メッセージの種類:
FirstInfo、BaseInfo、CmdResult - 受信コマンドの種類:
kill、peinject、runscript、rundir - 応答コマンドの種類:
rsp_kill、rsp_peinject、rsp_runscript、rsp_rundir
偽装されたIE8/Windows XPのユーザーエージェント文字列は特に注目に値する。これは3つのプラットフォームすべてにおいて時代錯誤であり、macOSまたはLinuxホスト上に存在する場合は強力な検出指標となる。
初期化と偵察
起動時に、各バリアントは次のようになります。
- セッションUID ( 16 のランダムな英数字)を生成し、以降のすべてのC2メッセージに含めます。
- OSとアーキテクチャを検出し、プラットフォーム固有の識別子(例:windows_x64、macOS、linux_x64)を報告します。
- 対象となる初期ディレクトリ(ユーザープロファイル、ドキュメント、デスクトップ、設定ディレクトリ)を列挙します。
- UID、OS識別子、およびディレクトリのスナップショットを含むFirstInfoビーコンを送信します。
初期化後、インプラントはメインループに入ります。最初のBaseInfoハートビートには、包括的なシステムプロファイルが含まれています。基盤となるAPIは異なるものの、収集されるデータの種類はすべてのプラットフォームで共通している。
| 収集されたデータ | Windowsソース | macOSソース | Linuxソース |
|---|---|---|---|
| ホスト名 | %COMPUTERNAME% 環境変数 | gethostname() | /proc/sys/kernel/hostname |
| ユーザー名 | %USERNAME% 環境変数 | getuid() + getpwuid() | os.getlogin() |
| OSのバージョン | WMI / レジストリ | sysctlbyname("kern.os製品バージョン") | プラットフォームシステム()+ platform.release() |
| タイムゾーン | システムタイムゾーン | localtime_r() | 日時.タイムゾーン |
| 起動時間 | システム稼働時間 | sysctl("kern.boottime") | /proc/uptime |
| インストール日 | レジストリ / WMI | stat("/") または sysctl | /var/log/installer または /var/log/dpkg.log の ctime |
| ハードウェアモデル | WMI | sysctlbyname("hw.model") | /sys/class/dmi/id/product_name |
| CPUタイプ | WMI | sysctlbyname() | プラットフォームマシン() |
| Process list | 完全なPID、セッション、名前、パス | popen("ps") (最大1000) | /proc の完全な列挙 (PID、PPID、ユーザー、コマンドライン) |
その後の心拍データは軽量で、インプラントが機能していることを確認するためのタイムスタンプのみが含まれている。
指揮指令
C2応答はJSONとして解析され、typeフィールドによってアクションが決定されます。これら3つのバリアントはすべて、同じ4つのコマンドを実行します。
終了 — 自己終了。rsp_kill の確認応答を送信して終了します。Windows版の永続化メカニズム(レジストリキー+バッチファイル)は、明示的にクリーンアップされない限り、killコマンドの実行後も存続します。macOS版とLinux版には、独自の永続化機能はありません。
runscript — スクリプト/コマンドの実行。オペレーターの主要な操作コマンド。スクリプトフィールド(実行するコード)とパラメータフィールド(引数)を受け入れます。スクリプトが空の場合、パラメータはコマンドとして直接実行されます。実行メカニズムはプラットフォームネイティブです。
| Elastic Platform | 実行メカニズム |
|---|---|
| Windows | PowerShell で -NoProfile -ep Bypass を使用 |
| macOS | /usr/bin/osascript 経由の AppleScript |
| Linux | サブプロセス.run(shell=True)経由でシェルを実行または、python3 -c を介して Python を実行する |
peinject — バイナリペイロード配信。Windows中心の命名規則(「PEインジェクト」)にもかかわらず、3つのプラットフォームすべてが、バイナリペイロードをドロップして実行する方法としてこれを実装している。
| Elastic Platform | Implementation |
|---|---|
| Windows | [System.Reflection.Assembly]::Load() を介したリフレクティブ .NET アセンブリの読み込み |
| macOS | Base64デコードしてバイナリを生成し、オペレーターが指定したパラメータで実行します。 |
| Linux | バイナリを/tmp/.<randomにBase64デコードします6文字の文字列>(隠しファイル)、subprocess.Popen() を介して起動します。 |
Windowsの実装では、ファイルのドロップなしでメモリ内実行が行われますが、AMSIを無効にしていないため、アセンブリのロード時に確実にフラグが立てられます。macOS版とLinux版は、バイナリファイルをディスクに書き込んで直接実行するという、よりシンプルな方法を採用している。
rundir — ディレクトリ列挙。パスを受け取り、詳細なファイル一覧(名前、サイズ、種類、作成/変更日時、ディレクトリの場合は子ファイルの数)を返します。オペレーターがファイルシステムを対話的に閲覧できるようにする。
機能概要
| 機能 | Windows (PowerShell) | macOS (C++) | Linux (Python) |
|---|---|---|---|
| 永続化 | レジストリ実行キー + 隠し .bat | なし | なし |
| スクリプトの実行 | PowerShell | osascript 経由の AppleScript | シェルまたはPythonインライン |
| バイナリインジェクション | cmd.exeへの反射型.NETロードインジェクション | バイナリドロップ+実行 | バイナリを/tmp/にドロップして実行します。 |
| 反鑑識 | 非表示ウィンドウ、一時ファイルのクリーンアップ | 隠し一時ファイル .scpt | 隠しファイル /tmp/.XXXXXX ファイル |
帰属
plain-crypto-js postinstallフックによって配信されるmacOS Mach-Oバイナリは、Mandiantが追跡しているC++バックドアであるWAVESHAPERと大きな重複が見られ、WAVESHAPERは北朝鮮関連の脅威クラスターであるUNC1069に起因するものとされている。
まとめ
今回のキャンペーンは、npmエコシステムがサプライチェーン攻撃の媒介手段として依然として魅力的な存在であることを示している。JavaScriptエコシステムで最も依存されているパッケージの1つにおける単一のメンテナーアカウントを侵害することで、攻撃者は数百万もの環境に影響を及ぼす可能性のある配信メカニズムを手に入れた。
このツールキットで最も信頼性の高い検出指標は、同時に最も奇妙な設計上の選択でもある。それは、IE8/Windows XPのユーザーエージェント文字列が、3つのプラットフォームすべてにおいて同一にハードコードされていることだ。これはC2サーバー側のルーティングにおいて一貫したプロトコルフィンガープリントを提供する一方で、最新のネットワーク上では容易に検出可能であり、macOSやLinuxホスト上では即座に異常と判断される。
Elastic Security Labsは、この活動クラスターの監視を継続し、新たな発見があればこの投稿を更新します。
MITRE ATT&CK
Elasticは、 MITRE ATT&CK フレームワークを使用して、企業ネットワークに対してAdvanced Persistent Threatが使用する一般的な戦術、手法、手順を文書化しています。
戦術(Tactics)
戦術は、テクニックまたはサブテクニックの理由を表します。 それは敵の戦術的な目標であり、行動を実行する理由です。
手法
手法は、敵対者がアクションを実行することによって戦術的な目標を達成する方法を表します。
- サプライチェーンの侵害:ソフトウェアの依存関係の侵害
- コマンドおよびスクリプトインタプリタ: JavaScript
- コマンドとスクリプト インタープリター: PowerShell
- コマンドおよびスクリプトインタープリタ:AppleScript
- Command and Scripting Interpreter: Unix Shell
- Command and Scripting Interpreter: Python
- ブートまたはログオン時の自動起動実行:レジストリ実行キー
- ファイルまたは情報の難読化
- マスカレード
- 隠しファイルと隠しディレクトリ
- プロセスインジェクション
- Indicator Removal: File Deletion
- システム情報の検出
- プロセスディスカバリー
- ファイルとディレクトリの検出
- Application Layer Protocol: Web Protocols
- 非標準ポート
- データエンコーディング:標準エンコーディング
- イングレスツール転送
観測
この研究では、次の観測量について議論しました。
| すぐれた監視性 | タイプ | 名前 | 参考 |
|---|---|---|---|
617b67a8e1210e4fc87c92d1d1da45a2f311c08d26e89b12307cf583c900d101 | SHA-256の | 6202033.ps1 | Windowsペイロード |
92ff08773995ebc8d55ec4b8e1a225d0d1e51efa4ef88b8849d0071230c9645a | SHA-256の | com.apple.act.mond | macOSペイロード |
fcb81618bb15edfdedfb638b4c08a2af9cac9ecfa551af135a8402bf980375cf | SHA-256の | ld.py | Linuxペイロード |
sfrclak[.]com | ドメイン | C2 | |
142.11.206[.]73 | IPv4-アドレス | C2 |
参照資料
上記の研究を通じて、以下のことが参照されました。
