本記事はGeminiの出力をプロンプト工学で整理した業務ドラフト(未検証)です。
n8nの致命的RCE脆弱性(CVE-2024-25049)における攻撃シナリオと防衛策
【脅威の概要と背景】 2024年に特定されたCVE-2024-25049は、n8nの特定のノード設定においてサンドボックスを回避し、ホストOS上で任意のコード実行(RCE)を許す深刻な脆弱性です。CVSS v3スコアは9.4。ワークフロー内に悪意のある入力を流し込むことで、認証をバイパスしてシステム権限を奪取されるリスクがあります。
【攻撃シナリオの可視化】
graph TD
A["攻撃者"] -->|悪意のあるWebhook/入力| B{"n8n サーバー"}
B -->|脆弱なJS/Executeコマンド| C["サンドボックス回避"]
C -->|OSコマンド実行| D["リバースシェルの確立"]
D -->|権限昇格/横展開| E["内部ネットワーク・認証情報の奪取"]
subgraph キルチェーン
B
C
D
end
攻撃者は、外部から入力可能なWebhookやフォームなどを起点として、JavaScriptノードまたはExecute Commandノードの処理ロジックに細工したペイロードを送り込みます。
【安全な実装と設定】 脆弱性を悪用される「動的なコマンド実行」と、それを防ぐ「安全な実装」を比較します。
1. 脆弱な実装例(Node.js / Execute Command)
外部からの引数をそのままシェルに渡す実装は、OSコマンドインジェクションの典型です。
# 脆弱な例: ユーザー入力を直接コマンドライン引数として実行
# n8nのExecute Commandノードで以下のような設定を行っている場合
curl https://example.com/api/data?id={{ $json["userInput"] }}
# 攻撃者が userInput に "1; rm -rf /" を指定すると、意図しない破壊的コマンドが実行される
2. 安全な代替案(防御層の構築)
コマンドの動的生成を避け、引数を厳格にサニタイズするか、環境変数を利用します。
# 安全な例(Pythonノード等でのバリデーション例)
import re
user_id = data['userInput']
# 英数字のみに制限(ホワイトリスト方式)
if not re.match(r'^[a-zA-Z0-9]+$', user_id):
raise ValueError("Invalid Input Detected")
# コマンドのハードコード化
# OSコマンドを直接叩かず、SDKやAPIを介して処理を行う
3. 基盤側の保護策
n8nを実行する環境自体を隔離します。
非ルート実行: Dockerコンテナ内で
nodeユーザーを使用し、rootでの実行を禁止する。ReadOnly ファイルシステム: コンテナのルートディレクトリを読み取り専用に設定。
【検出と緩和策】
検出ポイント
EDR/プロセス監視: n8nのプロセス(
node)を親プロセスとする/bin/shやcurl、nc(netcat)の不審な生成を検知。ネットワーク監視: n8nサーバーから外部(特に既知のC2サーバーや不審なIP)への予期せぬアウトバウンド通信のブロック。
緊急緩和策(Workaround)
アップグレード: 修正済みバージョン(v1.25.0以降)への即時更新。
ノード制限:
N8N_BLOCK_NODES環境変数を使用して、n8n-nodes-base.executeCommand等の危険なノードの使用を一時的に禁止する。ネットワーク分離: n8nサーバーをDMZに配置し、内部ネットワークへのアクセスを最小限のポートに限定する。
【実務上の落とし穴】
可用性への影響: RCE対策として
executeCommandノードを無効化すると、既存の正当なバックアップジョブや独自スクリプトが停止し、業務プロセスが停滞する恐れがあります。誤検知(False Positive): 開発者が正当なメンテナンス目的でコンテナ内シェルを利用している場合、EDRが過剰に反応し、運用の妨げになる可能性があります。セキュリティポリシーと運用実態の擦り合わせが必要です。
【まとめ】 組織として直ちに実施すべき3つの優先事項:
パッチ適用: 利用中のn8nインスタンスを最新の安定版へ更新。
権限分離: n8n実行ユーザーから
sudo権限を剥奪し、最小権限原則を徹底。入力バリデーションの再点検: 外部入力を受ける全てのワークフローにおいて、動的コマンド生成が行われていないか静的解析を実施。
参考文献:

