記事一覧に戻る
tutorial2026年5月24日19分で読めます

【無料】Aikido Zen を本番投入して1週間 — Inbound / Outbound / Package で見えてきたもの (途中経過)

aikido-community.jp に無料の runtime firewall「Aikido Zen」を本番投入してちょうど1週間。攻撃ボットが日常的に来ている事実、自分のアプリが外に叩いているhostname全量、runtimeで実際にロードされたパッケージ一覧 — Zenのダッシュボードで見えた実データを公開する途中経過レポート。

【無料】Aikido Zen を本番投入して1週間 — Inbound / Outbound / Package で見えてきたもの (途中経過)

aikido-community.jp に無料の runtime firewall「Aikido Zen」を入れて1週間。見えたことで一番大きかったのは、次の3つ。

攻撃者がすでに来ていた

ボットが米国・ウクライナ・スイス・アイルランドから、.env や .aws/credentials を片っ端から舐めに来ている。本番の Web サーバーは、立てた瞬間からこういう試行に晒されている。

自分のアプリが外に何を叩いているかが全部見えた

api.anthropic.com、api.x.com、fonts.googleapis.com など、自分のサイトから出ている通信先がすべてリストで見える。

ここに知らない hostname が一つでも増えた瞬間 — それは npm パッケージが侵害されて、攻撃者のサーバーに情報が送られ始めたサインかもしれない。最近の Shai-Hulud や durabletask のような supply chain 攻撃に対する、最後の防衛ラインがここで張れる。

実際に動いているパッケージの一覧も取れる

package.json に書いてある依存ではなく、runtime で実際にロードされたパッケージだけのリスト。「うちの本番、その侵害パッケージ動かしてる?」に正確に答えられる。

以下、実データと運用メモ。

1週間の数字 (Stats タブ)

aikido-community.jp の Zen ダッシュボードから直近1週間:

  • リクエスト数のピーク: 約 200 req/h
  • I/O operations: 約 135,000
  • Outbound HTTPS リクエスト: 約 4,800
  • SQL クエリ: 約 1,600
  • Attack Wave 検知: 5/21 から複数回

Aikido Zen Stats タブ — Requests / Events / Invocation details

Zen は 1.8.27 系で稼働。全 route を Detection Only モード (検知のみ・遮断しない) に置き、本番影響ゼロで観測している段階だ。

ここから、3つの方向 (inbound / outbound / package) で見えたものを順に紹介する。

1. Inbound: 「.env 狩り」が日常的に来る

Firewall タブを開くと、ここ数日で複数の Attack Wave が検知されている。Wave とは、同一 IP からの一連の不審リクエストを Zen が自動でグルーピングしたもの。

実際に来たリクエストの例 (米国 142.248.80.43)

GET /.env
GET /.env.local
GET /.env.production
GET /app/.env
GET /api/.env
GET /backend/.env
GET /.aws/credentials
GET /storage/.env
GET /.env.example
GET /.git/FETCH_HEAD
GET /.git/config
GET /.git/HEAD
GET /.git/refs/heads/main
GET /.git/logs/HEAD
GET /.git/refs/heads/master

Aikido Zen Firewall タブ — 米国 142.248.80.43 からの Attack Wave 詳細

User-Agent は Mozilla/5.0 (X11; Linux x86_64; rv:150.0) Gecko/20100101 Firefox/150.0。

これは特定の標的を狙ったものではなく、インターネット全体を機械的にスキャンする自動ボットの典型的な手口だ。Laravel や Node.js でよくある秘密情報の置き場所 (.env, .aws/credentials, .git/config) を片っ端から舐めていく。

似たパターンが各国から

直近2週間で同じ系統のパターンを検知した IP:

  • 91.239.78.101 (ウクライナ) — .env.bak, .env.old, /laravel/.env まで含む 15 パス
  • 179.43.146.227 (スイス)
  • 142.248.80.43 (米国)
  • 52.50.198.227 (アイルランド) — Aikido DAST 由来 (後述)

国は分散しているが、リクエスト内容のシグネチャはほぼ同じ。標的型ではなく、世界中の Web サーバーを無差別に掃いている自動スキャナの一群と読める。

被害は出ているか

aikido-community.jp は Next.js の standalone build + Docker 構成で、production の image には .env ファイルも .git/ ディレクトリもそもそも含まれていない (環境変数は docker compose 経由で runtime に注入し、.git/ は build context にも入れていない)。つまりこの攻撃はそもそも実害につながらない。ただし「実害が出ないから無視していい」のではなく、こうした試行が日常的に来ている事実を可視化できていることが Zen の価値の一つだ。

通常の nginx アクセスログを目で追っていればわかると言えばわかる話だが、Zen は同一 IP からの試行を Wave としてまとめ、攻撃の意図 (Path Traversal 系の偵察) で自動分類してくれる。ログの「ノイズ」を「シグナル」に変換してくれる、という言い方が近い。

Aikido DAST との区別

検知された Wave のうち、アイルランド (Dublin) からの 54.76.211.68 / 3.248.4.169 / 52.50.198.227 には Initiated by Aikido DAST というラベルが付く。これは Aikido 自身の DAST スキャナ (AWS eu-west-1 リージョン) から定期的に走っているテストだ。

運用上は次の手順を踏む。

  1. Aikido DAST ラベル付きの Wave は Flag as False Positive を選ぶ
  2. Disable protection for this route は押さない (本物の攻撃も通ってしまうため)

DAST ラベル付きと付かないものを切り分けるだけで、ダッシュボードの S/N 比はかなり改善する。

2. Outbound: ここが今回いちばん書きたかったところ

WAF と聞くと多くの人は「外から来るリクエストを止めるもの」と認識している。だが Zen の Outbound タブは別の世界を見せてくる。自分のアプリケーションが外に向かって何を呼び出しているか、その全量を runtime で記録している。

aikido-community.jp の Outbound 一覧 (直近7日間)

HostnamePortRequestsStatus
runtime.aikido.dev44312,700Allowed
guard.aikido.dev4431,300Allowed
fonts.googleapis.com44339Allowed
fonts.gstatic.com44338Allowed
api.x.com44311Allowed
www.aikido.dev4439Allowed
api.anthropic.com4433Allowed
cdn.jsdelivr.net4433Allowed

Aikido Zen Outbound タブ — アプリから外部に出ている全 hostname の一覧

それぞれの意味は次のとおり。

  • runtime.aikido.dev, guard.aikido.dev, www.aikido.dev — Zen 自身がポリシー取得とテレメトリ送信に使う
  • fonts.googleapis.com, fonts.gstatic.com — Web フォント
  • api.x.com — X (旧 Twitter) への記事自動投稿
  • api.anthropic.com — Claude API 呼び出し
  • cdn.jsdelivr.net — フロントエンド静的アセット

これだけ見ると「知ってる接続先しかない」普通の状態だ。が、ここに知らない hostname が一個でも増えた瞬間、それは異常を示す強いシグナルになる。

Supply chain 攻撃に対する runtime の防衛線

直近で記事化した durabletask の PyPI 改ざん (Shai-Hulud 系の "Here We Go Again" キャンペーン) や、過去の npm パッケージ侵害事例に共通するのは、

  1. 開発者が悪意のないつもりで npm install または pip install する
  2. 改ざんされたパッケージが post-install フックや初回実行時に動く
  3. 環境変数・トークン・SSH 鍵などを攻撃者のサーバーに送信する

という流れだ。1 と 2 のフェーズは静的スキャンや SBOM だけでは原理的に検知が難しい (改ざん直後でシグネチャがまだ流通していない)。

ここで効くのが Outbound 監視だ。3 のフェーズで attacker-c2.example.com のような未知の hostname に対する接続が runtime で発生した瞬間、Zen はそれを記録する。Allow list 方式に切り替えていればその時点で遮断もできる。

つまり Zen の Outbound は、SBOM や静的解析がカバーできない時間帯 (改ざん発覚前のゼロデイ期間) に対する、もう一枚の網として機能する。

「申請したAPIはこれ」より「実際に使われたAPIはこれ」のほうが強い

監査やコンプライアンスの場面でも、Outbound ログの意味は大きい。

「外部APIはこれを使う予定です」と申請書で示すよりも、「実際に使われているのはこれだけで、それ以外は出ていない」と runtime ログで示せるほうが、ずっと信頼できる。

前者は計画、後者は事実。重みが違う。

3. Packages: 静的 SBOM では見えない「実稼働コード」の一覧

Packages タブには、Zen が runtime で実際にロードを観測した npm パッケージが並ぶ。

aikido-community.jp の場合、抜粋すると次のような構成になっている。

  • @aikidosec/firewall 1.8.27 — Zen 本体
  • @next/env 15.5.12 — Next.js の環境変数ローダー
  • @prisma/client 5.22.0 — Prisma の DB クライアント
  • @npmcli/* — npm 内部ユーティリティ
  • chalk, abbrev など — 各種小規模ライブラリ

Aikido Zen Packages タブ — runtime でロードされたパッケージとバージョン

このリストの何がうれしいのか。package.json や package-lock.json を読めば依存はわかるはずだ、と思うかもしれない。

ところが、「lock ファイルに書かれている依存」と「runtime で実際に require / import されたコード」は同じではない。

  • devDependencies は本番では普通ロードされない
  • tree-shaking や条件付き import で落ちる依存もある
  • transitive dependency でも実行時に通らないコードパスがある

つまり、static SBOM は「コード上の脅威空間の最大値」を示すが、runtime SBOM は「今この瞬間、実害につながり得るコードの集合」を示している。

durabletask 事件のような侵害が公表されたとき、最初に聞かれるのは「うちの本番、それ動かしてる?」だ。grep で package.json を見て該当があっても、Packages タブで該当パッケージが In Use になっていなければ、影響範囲をより精密に絞れる。

4. 運用 Tips: 1週間で見えてきた暫定運用

1週間の実運用で見えてきた暫定的な運用方針を整理しておく。これらは現時点での判断であり、今後さらに調整していく可能性がある。

Detection Only から段階的に絞る

導入直後にいきなり全 route を Block モードにすると、誤検知で本番影響が出るリスクが高い。aikido-community.jp は1週間経過した現時点でも全 route を Detection Only に置いている。

ステップは次の順で進める予定。

  1. Detection Only で最低1週間運用し、検知パターンを蓄積する (← 現在地)
  2. 明らかな攻撃カテゴリ (SQL Injection, Path Traversal など) から Block に切り替える
  3. グレー判定は誤検知マークを積み上げてから判断する

Aikido DAST のラベルは False Positive 扱い

前述のとおり Aikido DAST 由来の Wave は False Positive フラグを立てる運用に統一する。ラベル機能があるので運用負荷は低い。

Outbound は最初 Detection Mode で

Outbound 側もいきなり遮断にすると、Web フォントや CDN が落ちて UI が崩れる。Detection Mode で一度全 hostname を洗い出し、想定外の hostname がないことを確認してから Allow list 化する手順を推奨する。

Rate Limiting は次の宿題

ダッシュボード上で「Setup Rate limiting」の警告が出ている。これは route ごとのレート制限ミドルウェアをまだ仕込んでいないためだ。次の宿題として、/api/* の書き込み系エンドポイントから順に設定していく予定。

まとめ

  • Zen 本番運用1週間時点で、Inbound / Outbound / Package の3方向で実データが溜まり始めている
  • Inbound では .env 狩りボットが日常的に来ている事実が可視化された
  • Outbound は supply chain 攻撃に対する runtime の最終防衛線として機能する
  • Packages は静的 SBOM では捉えきれない「実稼働コード」の inventory を提供する

次回は2〜4週間運用したあとの傾向変化、または Detection Only から Block への切り替え判断の記録を書く予定。Rate Limiting middleware の導入も並行して進めていく。

補足: これまでの記事との関係

aikido-community.jp ではこれまで、Aikido の守りを SDLC の時系列軸 で整理してきた。

  • 三層防御 (SDLC軸) 記事 — 第1層: IDE / ローカル, 第2層: PR / GitHub, 第3層: リポジトリ監視
  • Endpoint Protection 記事 — 第1層の死角 (IDE拡張・ブラウザ拡張・MCP・AIエージェントなど) を埋める
  • DAST / Surface Monitoring 記事 — 動いているアプリを外側から動的にテストする

これらはどれも、コードが本番に出るまで、あるいは本番に対する外部からのテストの話だった。本番で動いているアプリの内側で、実際のリクエストに対して何が起きているか という視点はまだ扱っていなかった。

今回の Zen はその視点を埋めるピース。SDLC の三層でも、外側から叩く DAST でもない、runtime 軸 の防御を担当する。本記事はその初回レポート。

A

Aikido Community Japan

公開日: 2026/5/24

最終更新: 2026/5/25

シェア:

ニュースを購読

セキュリティの最新情報をお届けします。

Aikido Community Japan からのお知らせの受信に同意します。詳しくはプライバシーポリシーをご確認ください。