axiosメンテナが語った北朝鮮UNC1069の手口、偽Slackに招待されTeams会議でRATを踏んだ
目次
前回の記事では、axiosの汚染バージョンに仕込まれたRATドロッパーの技術的な中身を解説した。だがコミュニティが本当に知りたかったのは「どうやってメンテナのアカウントが乗っ取られたのか」だった。
2026年4月5日追記: その後の公開証言から、これはaxios単発ではなく、Fastify、Lodash、dotenv、Mocha、Node.jsコア関係者まで横断的に狙うキャンペーンだったことが見えてきた。続報はこちら。
4月2日、axiosのリードメンテナJason Saaymanがポストモーテムを公開した。コメント欄でcorneliusroemerが「ソーシャルエンジニアリングの具体的な手口を共有してほしい」と求め、bcomnesが「再利用される手口だから共有することで他の人の防御にもなる」と後押しした。これに応える形で、Jasonが侵害の起点となった攻撃の全容を語った。
ソーシャルエンジニアリングの全手口
Jason本人がコメントで明かした手口を順に追う。攻撃者はGoogleのGTIG(Google Threat Intelligence Group)がUNC1069として文書化している北朝鮮系グループの手法を、Jason個人に最適化して実行した。
graph TD
A["実在企業の創業者に<br/>なりすまして接触"] --> B["偽Slackワークスペースに招待<br/>企業ブランドを完全再現"]
B --> C["LinkedIn投稿を共有<br/>チーム・他OSSメンテナの<br/>偽プロフィールを配置"]
C --> D["MS Teams会議を設定<br/>複数人が参加する体裁"]
D --> E["会議中に<br/>「何かが古い」と指摘"]
E --> F["Teams関連の更新に見せかけた<br/>ソフトウェアのインストール"]
F --> G["RAT: 端末を完全掌握"]
G --> H["npm認証情報を奪取<br/>2FA有効でもRAT経由で突破"]
H --> I["axios 1.14.1 / 0.30.4<br/>偽依存関係を注入してpublish"]
実在企業の完全クローン
攻撃者はまず、実在する企業の創業者になりすましてJasonに連絡した。「なりすまし」と言っても名前を騙っただけではない。企業そのもの、ブランド、コーポレートアイデンティティ、創業者の外見までクローンしている。
偽Slackワークスペース
Jasonは「本物の」Slackワークスペースに招待された。
they then invited me to a real slack workspace. this workspace was branded to the companies ci and named in a plausible manner. the slack was thought out very well, they had channels where they were sharing linked-in posts
ワークスペースは企業のブランドガイドラインに沿った名前とデザインで構成されていた。チャンネルにはLinkedIn投稿が共有されており、リンク先はおそらく本物の企業アカウント。さらにチームメンバーの偽プロフィールに加え、他のOSSメンテナのプロフィールまで用意されていた。
「自分だけが招かれたわけじゃない」という状況を演出して心理的な安心感を作る手口だ。
MS Teams会議
Slackでのやり取りの後、MS Teamsで会議が設定された。会議には複数人が参加しているように見えた。
the meeting said something on my system was out of date. i installed the missing item as i presumed it was something to do with teams, and this was the RAT.
会議中に「あなたの環境で何かが古い」と指摘される。JasonはTeams関連のアップデートだと思い、指示されたソフトウェアをインストールした。これがRAT(Remote Access Trojan、遠隔操作マルウェア)だった。
Jason本人の総評。
everything was extremely well co-ordinated looked legit and was done in a professional manner.
攻撃開始からRAT設置まで約2週間。ポストモーテムのタイムラインには「About 2 weeks before March 31: social engineering campaign initiated against the lead maintainer」とある。
2FAが無意味だった理由
DanielRufがコメント欄で「npmの2FAは有効にしていなかったのか」と問い、Jasonが回答している。
i have been told that once the RAT is on your machine they have full unilateral control of everything on your machine. and yes i did have 2fa enabled on my account.
2FAは有効だった。だがRATで端末を掌握されると、TOTP(時間ベースワンタイムパスワード)はソフトウェアで生成されるため攻撃者が同じ端末から読み取れる。ブラウザセッション、保存された認証情報、npmトークンすべてが攻撃者の手の中にある。
feross(Socket CEO)の指摘が端的だ。
Enable npm’s mandatory 2FA for publish, and use a hardware key if possible. TOTP on a compromised machine is not 2FA.
侵害済みの端末上のTOTPは2FAではない。端末が安全という前提が崩れた時点で、その上に積んだ防御は全部一緒に倒れる。
他のOSSメンテナにも同じ手口
Jasonの証言の直後、Node.jsエコシステムのパッケージメンテナvoxpelliがほぼ同じ構造の攻撃を受けた経験を共有した。
I had a similar incident a few weeks back where someone invited me to a podcast a week later and then invited me into a group with others who would be interviewed in the same podcast episode
voxpelliの場合は「ポッドキャスト収録」が口実だった。他の出演者がいるように演出し、SNS用の画像や事前質問まで送ってきた。収録直前になって接続トラブルを装い、macOS用の未署名アプリをインストールさせようとした。
Thankfully I was paranoid and didn’t run it
voxpelliは不審に思ってインストールを拒否。攻撃者は最後の手段としてcurlコマンドの実行を依頼し、それも拒否されると全会話を削除して消えた。後に解析したところ、インフォスティーラー(情報窃取マルウェア)だったという。voxpelliはMochaなどの高DLパッケージのメンテナで、標的としての価値が高い。
2件の比較。
| 要素 | axiosメンテナ(Jason) | Mochaメンテナ(voxpelli) |
|---|---|---|
| 口実 | 企業との協業 | ポッドキャスト出演 |
| 信頼構築 | 偽Slackワークスペース | 偽出演者グループ + 事前資料 |
| 準備期間 | 約2週間 | 約1週間 |
| マルウェア誘導 | Teams会議中の「更新」 | 収録直前の「接続トラブル」 |
| 結果 | RAT感染 | 拒否して回避 |
DanielRufはコメント欄で、偽の求人面接で特定のソフトウェアをインストールさせる手口も同系統だと指摘している。企業訪問、ポッドキャスト、求人。口実は変わっても構造は同じだ。
axiosは「ベストプラクティス」を導入済みだった
shaanmajidがnpmレジストリのメタデータを検証し、Gistで公開した分析が重要だ。axiosのv1.xは2023年からOIDC Trusted Publisherを導入しており、直近4リリース(1.13.4〜1.14.0)はすべてGitHub Actions経由でprovenance(出所証明)付きで公開されていた。
汚染版1.14.1にはOIDCバインディングもprovenanceもない。レジストリのメタデータを見れば一目で異常がわかる。だが、provenanceを検証するツールや仕組みは事実上オプトインで、チェックしている環境はほぼない。
shaanmajidの指摘で最も重要な部分。
The strictest package-level setting npm offers maintainers — “Require two-factor authentication and disallow tokens (recommended)” — does not block local
npm publish.
npmの最も厳格な設定でも、ローカルCLIからの npm publish を拒否できない。ブラウザで2FAの確認画面が開くが、RATがある端末上のソフトウェアTOTPなら突破は容易だ。Rustのcrates.ioにはOIDC経由のpublishのみ受け付ける設定があるが、npmにはない。
shaanmajidが挙げた防御策。
| 防御策 | レイヤ | 効果 |
|---|---|---|
| FIDO2ハードウェアキー | メンテナ個人 | RATがあっても物理キーは遠隔操作できない。今回唯一メンテナ側で取れた有効策 |
| OIDC-only publish強制 | レジストリ | ローカルCLIからのpublishをレジストリ側で拒否。crates.ioには存在する |
| 依存関係のクールダウン期間 | 消費者側ツール | 汚染版が公開されていたのは約3時間。3日のクールダウンがあれば自動取得されなかった。Dependabot、Renovate、bunなどが minimumReleaseAge をサポート |
| provenance検証 | 消費者側ツール | 正規リリースにはOIDC provenance、汚染版にはない。検証していれば即座に異常を検出できた |
攻撃者はissueも削除していた
ポストモーテムのタイムラインにもう1つ重要な記述がある。
March 31, around 01:00 UTC: community members file issues reporting the compromise. The attacker deletes them using the compromised account.
汚染版公開の約40分後、コミュニティメンバーが異常に気づいてissueを立てた。攻撃者はJasonの侵害済みアカウントを使ってそれを削除した。検知を妨害し、汚染版の公開時間を延ばすための行動だ。
これに対してaxiosコラボレーターのDigitalBrainJSが、自身のアカウント権限がJasonより低いにもかかわらず、PR #10591で汚染バージョンの廃止処理を進め、npmに直接連絡して削除に持ち込んだ。ferossはSocketの自動検出が公開から6分以内に危険判定したと報告しているが、npmからの削除はそこから約2時間かかった。
npxという見落とされがちな感染経路
ahmadnassriが指摘した npx の問題も無視できない。
npxinvocations produce a non-deterministic dependency resolution at run-time, no package-lock trace.
npx は実行時に依存関係を解決するため、lockfileに痕跡が残らない。CI/CDやMCPツールのセットアップドキュメントが npx <package>@latest を推奨している現状では、汚染版が公開されていた約3時間のウィンドウで npx 経由でaxiosを間接的に引き込んだ環境も侵害対象になる。lockfileを確認する通常の影響判定では、この経路を検出できない。