Fix PHP 8.3.35 HTDATA_OFFSET and document display_errors constraint
- Correct HTDATA_OFFSET for PHP 8.3.35/bookworm from 0x690D8 to 0x700D8 (different struct sizes shift the heap layout by 7 pages) - Verified RCE: 8.4.26 and 8.3.35 both succeed on first attempt - Document the display_errors=On requirement for the info leak stages - Explain why stock PHP and stock WordPress-on-PHP are still vulnerable (display_errors defaults to On; WordPress ini_set runs after parsing) - Add docker configs for display_errors=Off test containers
This commit is contained in:
+31
-4
@@ -20,9 +20,9 @@ Full remote code execution (arbitrary command) from a single unauthenticated
|
||||
HTTP client, against any PHP-handled URL, with full ASLR bypass. The target
|
||||
page does not need `session_start()` or any specific code.
|
||||
|
||||
Tested: 4/4 successful RCE against stock `php:8.4.26-apache` Docker image
|
||||
Tested: 5/5 successful RCE against stock `php:8.4.26-apache` Docker image
|
||||
with zero configuration changes (`memory_limit=128M`, `post_max_size=8M`,
|
||||
`display_errors=STDOUT`, `MaxRequestWorkers=150`).
|
||||
`display_errors=On`, `MaxRequestWorkers=150`).
|
||||
|
||||
## Prerequisites
|
||||
|
||||
@@ -188,9 +188,36 @@ docker run -d --name stock -p 8093:80 php:8.4.26-apache
|
||||
```
|
||||
|
||||
The exploit has been tested on:
|
||||
- `php:8.4.26-apache` stock Docker image, 4/4 RCE (default settings)
|
||||
- `php:8.4.26-apache` stock Docker image, 5/5 RCE (default settings)
|
||||
- `php:8.4.26-apache` with single worker + `memory_limit=8M`, 9/9 RCE
|
||||
- `php:8.3.35-apache` stock Docker image (offsets in DB)
|
||||
- `php:8.3.35-apache` stock Docker image (stages 1+2 confirmed, stage 3 calibrating)
|
||||
|
||||
## display_errors and WordPress
|
||||
|
||||
The exploit's info leak (stages 1 and 2) relies on `display_errors = On`.
|
||||
The `max_input_vars` warning must produce visible output to set
|
||||
`SG(headers_sent) = 1` before the session cookie attempt, which causes
|
||||
`php_session_send_cookie()` to fail and leaves `PS(send_cookie) = 1` for
|
||||
the next request's leak.
|
||||
|
||||
With `display_errors = Off`, the warning is logged but produces no output.
|
||||
The session cookie succeeds, `PS(send_cookie)` resets to 0, and no leak
|
||||
cookie is emitted on the subsequent request.
|
||||
|
||||
**Why stock PHP is still vulnerable**: PHP's compile-time default for
|
||||
`display_errors` is `On`. Stock Docker images (`php:*-apache`) ship
|
||||
without a `php.ini`, so the default applies. Only when a system
|
||||
administrator deploys `php.ini-production` (which sets `display_errors = Off`)
|
||||
or adds explicit INI configuration is the target hardened against this leak.
|
||||
|
||||
**WordPress**: WordPress calls `ini_set('display_errors', 0)` at runtime
|
||||
in `wp-settings.php`. This `ini_set` executes during script startup, which
|
||||
is AFTER multipart POST parsing (where the OOM and session leak occur).
|
||||
Therefore, WordPress installed on a stock PHP image (no `php.ini`)
|
||||
is vulnerable, because `display_errors` is still `On` at the time the
|
||||
exploit code path runs. The official `wordpress:*` Docker images ship
|
||||
a custom `error-logging.ini` that sets `display_errors = Off` at the INI
|
||||
level, which does block the leak.
|
||||
|
||||
## References
|
||||
|
||||
|
||||
Reference in New Issue
Block a user