ラボ実証チェーン(docs/06 dp6-rp+dp-rce / docs/08 R2 / lab/xpoc-rce.py)を 自己完結した2ファイルに縮約したもの。
| ファイル | 役割 |
|---|---|
poc.php |
被害アプリ役。①Gadgetクラス(__wakeup/__destruct→@system($note)) ②?poison=1&sid=¬e=で$_SESSION保存機能(アプリ依存のpoisoningベクトル) ③通常リクエストではrequest_parse_body()をmid-script呼び出し(8.4流epr=0パターン) |
poc.py |
攻撃側。POISON(GET)→FIRE(未認証multipart・クッキー不要)→PROOF表示。POC_HOST/POC_PORT/POC_SCRIPT/POC_PAYLOAD環境変数対応 |
run_lab.sh |
ランチャー(推奨)。8.4.26/8.4.27両コンテナを起動しPoCを撃って差分(RCE成立 vs ゲートで不発)を一括表示 |
[1] POISON アプリの$_SESSION保存機能で任意SIDの行に Gadget を植入
(実戦ではComposerガジェット。ここでは自前クラス)
[2] FIRE 未認証 multipart 1本:
name="PHPSESSID" フィールド ← 攻撃者SID(検証なしintake: session.c:3249)
name="PHP_SESSION_UPLOAD_PROGRESS" ← progress機構 起動
ファイル部品 ← FILE_START → session lifecycle
→ request_parse_body() の mid-script で rfc1867 → progress update() 内
php_session_initialize() → 植入済み行が unserialize され
__wakeup/__destruct が「C世界の途中」で発火 → @system("id")
[3] PROOF /tmp/POP_PROOF(発火時刻) + /tmp/RCE_PROOF(uid=... )
| 対象 | POP_PROOF | RCE_PROOF |
|---|---|---|
| 8.4.26(脆弱/現行stable相当) | poison破棄1 + FIRE由来 wake/destruct 2対 | uid=0 出力 = RCE成立 |
| 8.4.27(修正版) | poison破棄1 のみ(FIRE由来0行) | (空) = 不発 |
8.4.27で消えるもの = PG(modules_activated) ゲート
(「request_parse_body(). Do not run here as it corrupts the session.」)
- progress内decodeのincomplete_classes_only化 → 本PoCはそのまま回帰テストになる。
推奨: run_lab.sh を使う(CWDどこからでもOK・パス解決をスクリプトがやる)
./run_lab.sh # 8.4.26(脆弱)と8.4.27(修正)の両方を起動して比較
./run_lab.sh vuln # 脆弱版のみ
./run_lab.sh fix # 修正版のみ出力の見方:
- 8.4.26 …
POP_PROOFに FIRE 由来の__wakeup/__destruct2対、RCE_PROOFにuid=...= RCE成立 - 8.4.27 … FIRE 由来の magic method は0行、
RCE_PROOFは空 = ゲートでkill(回帰テスト)
手動でやる場合の注意(2026-10-21 の事故再発防止):
# 必ず php-up-lab/ で実行するか、-v のパスを実在に合わせること。
# 存在しないホストパスを -v に渡すと Docker が「空ディレクトリ」を勝手に作り、
# コンテナ内の poc.php がディレクトリ化して 404 "No such file or directory" になる。
cd /path/to/php-up-lab # poc.php は php-up-lab/poc/poc.php
docker run -d --name phpup-cli-poc -p 127.0.0.1:8099:8099 \
-v "$PWD/poc/poc.php":/var/www/html/poc.php:ro \
php-up-verify:8.4.26-asan \
/opt/php/bin/php -d session.save_path=/tmp/sessions \
-d enable_post_data_reading=0 -d session.use_strict_mode=0 \
-d session.upload_progress.enabled=1 -d session.upload_progress.cleanup=0 \
-S 0.0.0.0:8099 -t /var/www/html
python3 poc/poc.py # poc/ の中なら: python3 poc.py
docker exec phpup-cli-poc cat /tmp/POP_PROOF /tmp/RCE_PROOF注意: poison リクエスト自体のオブジェクト破棄でシンクが走るノイズを防ぐため、
__destruct は $_GET['poison'] リクエストでは無音化してある
(RCE_PROOF は FIRE リクエスト由来のみ)。
ペイロードは id 級マーカーのみ。破壊的操作・実環境への無断実行は禁止。