
WordPress向けに固定されたDocker公式イメージ1件に対するCVE-2026-111497のRCE PoC
このソースのみのPoCは、固定されたDocker公式WordPressイメージ1つに対して、未認証のコマンド実行を再現します。
1回のpingback.pingリクエストにより、WordPressは同一のPHPリクエスト中に攻撃者のURLを2回取得します。最初のレスポンスがBrotliを介してPHPハンドラを破壊します。リトライヘッダがBashを起動し、ラボのフラグを返します。
このプロファイルはターゲット固有です。現在のWordPressイメージ、他のダイジェスト、あるいはWordPress Coreのメモリエラーについて何ら主張するものではありません。
警告: このPoCは、所有するシステム上の同梱ラボでのみ実行してください。動作するRCEペイロードを含みます。
/flag.txtを読み取り、フラグがXML-RPCレスポンスで返されます。shからbash、sleepへのプロセスチェーンを記録します。| 項目 | 値 |
|---|---|
| ターゲット | docker.io/library/wordpress@sha256:806680ba62232c4c300fb9dcc9f89d08e9e8c2bfc59837a1f58716f8648306d5 |
| イメージID | c64dd89c00079939f18d70489e7c3e30cb071e8581824ab2de688f9f4d70d076 |
| プラットフォーム | Linux amd64、Debian 13.7 |
| アプリケーション | WordPress 7.1.3、Apache 2.4.69 prefork |
| ランタイム | PHP 8.3.36 NTS |
| デコーダ | libbrotli1:amd64 1.1.0-2+b7 |
このLinux/amd64マニフェストは、公開当時にwordpress:latestによって選択されていました。現在のlatestタグはもはやこれを選択しません。
ラボはこの未改変のDocker公式イメージをrootless Podmanで実行します。Brotliライブラリを注入することはありません。
CVE-2026-111497がデコーダの破壊を提供します。WordPressがpingback.pingを介して未認証の取得経路を提供します。
不正なストリームは、稼働中のsystemハンドラポインタからstrtolowerハンドラへ6バイトをコピーします。両方のポインタは同じASLRでロードされたlibphp.soベースを使用します。したがって、このプロファイルは絶対アドレスのリークを必要としません。
このプロファイルは依然として、正確なBrotli、PHP、glibc、cURL、Requests、Apache、アロケータ、およびリクエスト履歴に依存します。最初のレスポンスは161バイトのヘッダと23,069,816バイトのボディを使用します。オリジンは23,069,752バイトを送信し、1秒待機してから最後の64バイトを送信します。
デコーダは破壊後にエラーを返します。RequestsはCURLE_BAD_CONTENT_ENCODINGの後にコンテンツデコードなしでリトライします。その最初のヘッダ名が改変されたハンドラに到達し、固定のBashコマンドを起動します。
アプリケーション経路には以下の条件が必要です:
/xmlrpc.phpに到達可能で、pingback.pingが有効であること。ラボはプラグインや被害者側の計装なしでこれらの条件を作り出します。
generate_payloads.pyが権威あるペイロードソースです。リポジトリはビルド済みのペイロードバイナリを追跡していません。
ジェネレータはPython標準ライブラリのみを使用します。オフラインで動作し、トラフィックを送信したりコマンドを実行したりしません。RFC 7932からプロファイル定数とシリアライゼーションステージを定義します。
verify.shはすべてのフラグメントを再生成します。それらのサイズ、ハッシュ、中間ビットオフセット、および1ビットセレクタの関係を検証します。
テスト済みのホストは、amd64上のWSL2でUbuntu 24.04.4を使用しました。rootless Podman 4.9.3、Bash 5.2.21、Python 3.12.3を使用しました。
最小要件は、Linux amd64、rootless Podman、Bash、Python 3.8以降、ASLRモード2、および標準GNUユーザーツールです。ポート18170とサブネット93.184.218.0/24を空けておくか、代替を選択してください。SELinuxが強制モードのホストはバインドマウントを拒否する可能性があります。
ラボを実行する前に、不変イメージをプルしてください:
podman pull docker.io/library/wordpress@sha256:806680ba62232c4c300fb9dcc9f89d08e9e8c2bfc59837a1f58716f8648306d5
podman pull docker.io/library/wordpress@sha256:65d5f185a6f539803a177ea9cdd5ad632ae24427bea114447e67a6fcd5d8bfe8
podman pull docker.io/library/mariadb@sha256:33a6653ab666774f48818120045f9367a81cd4c54c027412fe294a7d1274e2dc
スクリプトを実行可能にし、その後ソースパッケージを検証します:
chmod +x generate_payloads.py verify.sh run.sh
./verify.sh
新しいタグを付けて各モードを実行します:
| モード | コマンド | 期待される結果 |
|---|---|---|
| Positive | ./run.sh standard | フラグを返し、PoC positive: を出力する |
| Observable | ./run.sh observable | さらに、可視の bash および sleep プロセスを記録する |
| Selector | ./run.sh selector | リトライするが、フラグをレスポンスに含めない |
セレクタはバイトオフセット1066の1ビットを変更します。これは同一イメージ内の因果的コントロールであり、固定デコーダのコントロールではありません。
オプション引数はモード、タグ、ホストポート、および第3ネットワークオクテットです:
./run.sh standard trial2 18171 219
ランナーは証拠を runs/<tag>/ に書き込みます。主要なファイルは次のとおりです:
VERDICT.txt: 結果とリクエスト数client-request.raw と client-response.raw: 受信したワイヤデータorigin-evidence/origin-events.json: 送信リクエストとリトライヘッダーの両方oracle-match.txt: レスポンス内のフラグ一致payloads/identity.json: 生成されたプロファイルのメタデータMANIFEST.sha256: すべての証拠ファイルのハッシュランナーは内部の Podman ネットワークを使用し、WordPress を 127.0.0.1 でのみ公開します。クライアントはターゲットアドレスを受け付けません。オリジンはコマンド入力を受け付けません。固定コマンドは合成フラグのみを読み取ります。
ランナーは Apache が起動する前に、Apache の環境からフラグ値を削除します。また、新しい認証情報を作成し、現在の実行のリソースのみを削除します。
レスポンスの分割とプロセス履歴はエクスプロイトの入力です。実行が失敗した場合は、変更していないプロファイルを新しいタグで繰り返してください。失敗した実行の後にアドレスやペイロードのバイトを調整しないでください。
このパッケージは、イメージダイジェスト、PHP ビルド、アーキテクチャ、アロケータ、レスポンススケジュールにわたる移植性を確立するものではありません。異なるターゲットでは実行が停止するか、クラッシュのみが発生する可能性があります。
アップストリームは、メンテナンスされている Brotli ブランチを 1.0.10、1.1.1、1.2.1 で修正しました。ディストリビューションのベンダーは修正をバックポートできます。表示されているバージョンだけでなく、ベンダーのアドバイザリとパッケージの変更履歴を使用してください。