Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions COVERAGE.es.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ Definiciones de estado:
| Aborto OOM / Corrupción de heap | Afectado por versión; no explotado | fail | pass | pass (0/3) | Control 8.4.27: 0/5 sin abortos; ramas corregidas bloqueadas en etapa 1 |
| RCE, `display_errors=On`, ASLR On | No probado | fail (3/3) | pass (0/5) | pass (0/3) | mod_php prefork; re-ejecución de control 3/3 en el mismo arnés |
| RCE, `display_errors=Off`, ASLR Off | No probado | fail (3/3) | pass | No probado aquí | Build con offsets calibrados; ramas fijas no probadas en este perfil |
| RCE, `display_errors=Off`, ASLR On | No probado | No alcanzado: cadena de cookie 0/3 controlado; cadena 9bie también 0/3, se detiene en la etapa 1 (su 8/8 requiere `display_errors=On`) | pass | No probado | Reclamación 12/12 retractada; la cookie de 4000 B depende del estado y la lectura de 0xC8000 necesita salida de errores para la etapa 1 |
| RCE, `display_errors=Off`, ASLR On | No probado | **alcanzado 10/10** con la cadena `pure/` del upstream en stock 128M/150 workers (10 bases `libphp` distintas, ejecución real de comando), 0/5 en 8.4.27; nuestra cadena de cookie 0/3 y la cadena 9bie anterior 0/3 | pass | No probado | Reclamación 12/12 retractada; la cookie de 4000 B depende del estado y la lectura de 0xC8000 necesita salida de errores para la etapa 1 |
| FPM decode OOM / `BG(unserialize)` colgante | No probado | Crash UAF determinista (502) comprobado en watchpoint; con struct reclamado por multipart, escritura controlada de 16 B en `sapi_module.ub_write = &system` -> RCE en lab | No probado | No probado | CVE-2026-109619; mecanismo por defecto = enlace de free-list sobre `used_slots`; variante controlada = fake `var_dtor_entries` (ASLR off, sesión de 24 B); 8.4.27 estable |
| Divulgación de memoria vía cookie | No probado | Parcial (cookie de 4000 B revela punteros de heap; HashTable inalcanzable; libphp acotado a ~1.88 MB con esa lectura, fijado con `zend_string` de 0xC8000 -- cadena 9bie, 8/8 con ASLR On) | pass | pass (0/3) | Dependiente de geometría; ramas fijadas: fuga no reproducible |
| CVE-2026-115560 (Informativo, 2026-10-23) | No probado | No probado | No corregido | No probado | Condición estrecha (config `php_binary` + `ini_set()` a `php` en runtime); mitigación `session.upload_progress.enabled=0` |
Expand Down Expand Up @@ -71,7 +71,7 @@ Ramas fijadas 8.3.36 y 8.2.35 (mismo arnés, 3 corridas c/u): 0/3, bloqueadas en

| PoC / Herramienta | Reclamación | Estado Independiente |
|---|---|---|
| 9bie | Bypass de ASLR / RCE | pass en laboratorio con `display_errors=On` (8/8 ASLR On, 8 bases distintas; 5/5 Off, 1 base); 0/3 con `display_errors=Off` + ASLR On en el mismo perfil de laboratorio; `raw/9bie-aslr-on-8run.txt`, `raw/9bie-aslr-off-5run.txt`, `raw/9bie-display-off-3run.txt`; el autor reporta 10/10 con el perfil stock de 150 workers; dependiente de la memoria del host |
| 9bie | Bypass de ASLR / RCE | pass en laboratorio con `display_errors=On` (8/8 ASLR On, 8 bases distintas; 5/5 Off, 1 base); la cadena anterior 0/3 con `display_errors=Off` + ASLR On; la cadena `pure/` del upstream **10/10** con `Off` + ASLR On en el perfil stock 128M/150 workers (`raw/9bie-pure-off-aslr-on-10run.txt`); `raw/9bie-aslr-on-8run.txt`, `raw/9bie-aslr-off-5run.txt`, `raw/9bie-display-off-3run.txt`; el autor reporta 10/10 con el perfil stock de 150 workers; dependiente de la memoria del host |
| ikow A/B/C | Cadenas | Código analizable; A/C requieren prerrequisitos; B es local |
| ikow D/E | Scripts de verificación | Públicos; exploits completos cerrados/de pago |
| GoldraK scanner A/C/E | 24/24 vulnerable | pass para A/C/E; no mide OOM; 8.4.27 omitido de la tabla |
Expand All @@ -83,7 +83,7 @@ Ramas fijadas 8.3.36 y 8.2.35 (mismo arnés, 3 corridas c/u): 0/3, bloqueadas en

| Capa | Qué se probó | Generalización |
|---|---|---|
| Oficial `php:8.4.26-apache` | RCE 3/3 On/ASLR On; 3/3 Off/ASLR Off; cadena de cookie 0/3 Off/ASLR On, cadena 9bie 8/8 con ASLR On y 0/3 con ASLR On + `display_errors=Off` | Primitiva a nivel de motor PHP; dependiente del build/allocator |
| Oficial `php:8.4.26-apache` | RCE 3/3 On/ASLR On; 3/3 Off/ASLR Off; cadena de cookie 0/3 Off/ASLR On, cadena `pure/` de 9bie 10/10 con `Off` + ASLR On en stock 128M (0/3 en 8M) | Primitiva a nivel de motor PHP; dependiente del build/allocator |
| Oficial `php:8.4.27-apache` | 0/5 control | Parche oficial para la clase OOM |
| Nextcloud 33.0.x test, PHP 8.4.21 `mod_php` | Versión/configuración validada; RCE no ejecutado | Primitiva independiente de la app; dependiente del despliegue |
| FPM A/C/E | RCE con prerrequisitos de laboratorio | Dependiente de aplicación/configuración |
Expand Down
15 changes: 9 additions & 6 deletions COVERAGE.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ Status definitions:
| OOM abort / heap corruption | affected by version; not exploited | fail | pass | pass (0/3) | 8.4.27 control: 0/5, no aborts; fixed branches blocked at stage 1 |
| RCE, `display_errors=On`, ASLR on | not tested | fail (3/3) | pass (0/5) | pass (0/3) | mod_php prefork; control rerun 3/3 in the same harness |
| RCE, `display_errors=Off`, ASLR off | not tested | fail (3/3) | pass | not tested here | offset-calibrated build; fixed branches not exercised in this profile |
| RCE, `display_errors=Off`, ASLR on | not tested | not achieved: cookie-only chain 0/3 controlled; 9bie chain also 0/3, stops at stage 1 (its 8/8 needs `display_errors=On`) | pass | not tested | 12/12 claim withdrawn; the 4000-byte cookie is state-dependent, and the 0xC8000 read needs error output for stage 1 |
| RCE, `display_errors=Off`, ASLR on | not tested | **achieved 10/10** with the upstream `pure/` chain on stock 128M/150 workers (10 distinct `libphp` bases, real command execution), 0/5 on 8.4.27; our cookie-only chain 0/3 and the previous 9bie chain 0/3 | pass | not tested | 12/12 claim withdrawn; the 4000-byte cookie is state-dependent, and the 0xC8000 read needs error output for stage 1 |
| FPM session decode OOM / stale BG | not tested | deterministic UAF crash (502) verified with watchpoint; with the multipart-reclaimed struct, controlled 16-byte write to `sapi_module.ub_write` = `&system` -> command execution in the lab | not tested | not tested | CVE-2026-109619; default mechanism = allocator free-list encoding over `used_slots`; controlled variant = fake `var_dtor_entries` (ASLR off, planted 24-byte session); 8.4.27 stable (early reset) |
| Memory disclosure via cookie | not tested | partial (4000-byte cookie discloses heap pointers; session table not reachable; libphp narrowed ~1.88 MB at that read size, pinned with a `len=0xC8000` forged `zend_string` -- 9bie chain, 8/8 ASLR-on reproduced) | pass | pass (0/3) | geometry-dependent; fixed branches: leak not reproducible |
| CVE-2026-115560 (informational, 2026-10-23) | not tested | not tested | not fixed | not tested | narrow condition (config `php_binary`/`php_serialize` + runtime `ini_set()` switch to `php`); mitigation `session.upload_progress.enabled=0` |
Expand Down Expand Up @@ -71,7 +71,7 @@ leak). Raw: `raw/fixed-branches-verify.txt`.

| PoC | Claim | Independent status |
|---|---|---|
| 9bie | ASLR bypass / RCE | pass in the lab with `display_errors=On` (8/8 ASLR-on, 8 distinct bases; 5/5 off, 1 base); 0/3 with `display_errors=Off` + ASLR on in the same lab profile; `raw/9bie-aslr-on-8run.txt`, `raw/9bie-aslr-off-5run.txt`, `raw/9bie-display-off-3run.txt`; author reports 10/10 on the stock 150-worker profile; host-layout dependent |
| 9bie | ASLR bypass / RCE | pass in the lab with `display_errors=On` (8/8 ASLR-on, 8 distinct bases; 5/5 off, 1 base); the previous chain 0/3 with `display_errors=Off` + ASLR on; the upstream `pure/` chain **10/10** with `Off` + ASLR on on the stock 128M/150-worker profile (`raw/9bie-pure-off-aslr-on-10run.txt`); `raw/9bie-aslr-on-8run.txt`, `raw/9bie-aslr-off-5run.txt`, `raw/9bie-display-off-3run.txt`; author reports 10/10 on the stock 150-worker profile; host-layout dependent |
| ikow A/B/C | chains | readable; A/C need prerequisites; B local |
| ikow D/E | verification scripts | public; full exploits not public |
| GoldraK A/C/E scanner | 24/24 vulnerable | pass for A/C/E; does not measure OOM; 8.4.27 omitted from the table |
Expand All @@ -83,7 +83,7 @@ leak). Raw: `raw/fixed-branches-verify.txt`.

| Layer | What was tested | Generalization |
|---|---|---|
| Official `php:8.4.26-apache` | RCE 3/3 On/ASLR on; 3/3 Off/ASLR off; cookie-only chain 0/3 Off/ASLR on, 9bie chain 8/8 with ASLR on and 0/3 with ASLR on + `display_errors=Off` | PHP-level primitive; build/allocator dependent |
| Official `php:8.4.26-apache` | RCE 3/3 On/ASLR on; 3/3 Off/ASLR off; cookie-only chain 0/3 Off/ASLR on, 9bie `pure/` chain 10/10 with `Off` + ASLR on at stock 128M (0/3 at 8M) | PHP-level primitive; build/allocator dependent |
| Official `php:8.4.27-apache` | 0/5 control | Patch for the OOM class |
| Nextcloud 33.0.x test deployment, PHP 8.4.21 `mod_php` | Version/config validated; RCE not executed | App-independent primitive; deployment-specific |
| FPM A/C/E | RCE with lab prerequisites | App/config-dependent |
Expand All @@ -103,9 +103,12 @@ leak). Raw: `raw/fixed-branches-verify.txt`.
discloses heap (id chunk base) but never the session HashTable, and at the 4000-byte read it
narrows `libphp` to a 1.88 MB window. A larger OOB read (`len=0xC8000` forged `zend_string`)
pins `libphp` and the 9bie chain reaches RCE with ASLR on; we replicated it 8/8 ASLR-on and
5/5 off. What stays closed in our measurements is the combination: the channel is single-shot
per OOM and `mod_php`-only, and on `mod_php` the leak and the stale-`BG(unserialize)`
primitive are mutually exclusive.
5/5 off. What stays closed is the combination **with our cookie chain**: that channel is single-shot
per OOM and `mod_php`-only, and there the leak and the stale-`BG(unserialize)` primitive are
mutually exclusive. That does not bound the family: the upstream `pure/` chain does not use
`BG(unserialize)` and closes `Off` + ASLR-on at the stock 128M geometry — 10/10 measured on
2026-11-09, 0/5 on 8.4.27. At 8M the chain is 0/3 and needs recalibration, and the cold-start
rate is not characterized.
- Kernel/allocator portability is not solved; public PoC results vary by host.
`PORTABILITY.md` records the measured matrix behind that sentence: `KeepAlive On`,
proxy buffering and an unsaturated worker pool each break the chain on their own.
Expand Down
4 changes: 4 additions & 0 deletions PORTABILITY.es.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,10 @@ cadena y cuáles solo lo parecen.
| `Off`, `8M`, 1 worker, imagen oficial, ASLR **encendido** | **0/3** — bloqueado por el leak de `libphp` | n/d |
| `On`, `8M`, 1 worker, kernel pve 7.0, ASLR encendido | 0/3 | n/d |

> La fila `Off` + ASLR On de arriba es el **perfil de laboratorio de 8M**. La geometría stock es
> otra celda: con `php.ini-production` (128M) y la cadena `pure/` del upstream, `display_errors=Off`
> con ASLR On da 10/10 — ver `COVERAGE.es.md` §1 y `raw/9bie-pure-off-aslr-on-10run.txt`.

## Lo que dice la matriz

1. **`memory_limit` no es el candado: lo es `post_max_size`.** Con 512M/480 MB la cadena corre
Expand Down
5 changes: 5 additions & 0 deletions PORTABILITY.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,11 @@ and which ones only look like gates.
| `Off`, `8M`, 1 worker, official image, ASLR **on** | **0/3** — blocked by the `libphp` leak | n/a |
| `On`, `8M`, 1 worker, kernel pve 7.0, ASLR on | 0/3 | n/a |

> The `Off` + ASLR-on row above is the **8M lab profile**. The stock geometry is a different
> cell: with `php.ini-production` (128M) and the upstream `pure/` chain, `display_errors=Off`
> with ASLR on gives 10/10 — see `COVERAGE.md` §1 and
> `raw/9bie-pure-off-aslr-on-10run.txt`.

## What the matrix says

1. **`memory_limit` is not the gate; `post_max_size` is.** At 512M/480 MB the chain runs the
Expand Down
4 changes: 2 additions & 2 deletions README.es.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
# php2shell — Verificación Independiente y Auditoría de Límites de Explotación
### CVE-2026-109618 · CVE-2026-109619 · CVE-2026-115560

[![Release](https://img.shields.io/badge/Release-v1.10.0_(2026--11--09)-0284c7?style=flat-square&logo=github)](https://github.com/JoshRob297/php2shell-research/releases/tag/v1.10.0)
[![Release](https://img.shields.io/badge/Release-v1.11.0_(2026--11--09)-0284c7?style=flat-square&logo=github)](https://github.com/JoshRob297/php2shell-research/releases/tag/v1.11.0)
[![Target](https://img.shields.io/badge/Objetivos_PHP-8.2_·_8.3_·_8.4_·_8.5-334155?style=flat-square)](#)
[![CVSS](https://img.shields.io/badge/CVSS_v4.0-9.2_CRÍTICO-b91c1c?style=flat-square)](#)
[![ASLR](https://img.shields.io/badge/ASLR-Ventana_Cookie_1.88_MB-d97706?style=flat-square)](#)
Expand Down Expand Up @@ -103,7 +103,7 @@ La evaluación empírica de la primitiva E-OOM en PHP-FPM 8.4.26 (`fpmdbg` detr
|---|---|---|:---:|---|
| mod_php 8.4.26 | `display_errors=On` · ASLR On | RCE alcanzado (3/3 ejecuciones exitosas, `uid=33`) | `CONFIRMADO` | Sección 1 |
| mod_php 8.4.26 | `display_errors=Off` · ASLR Off | RCE alcanzado (3/3 ejecuciones exitosas, `uid=33`) | `CONFIRMADO` | Sección 1 |
| mod_php 8.4.26 | `display_errors=Off` · ASLR On | Cadena de cookie: solo divulgación de heap con 4000 B (ventana de 1.88 MB), 0/3 RCE. Cadena 9bie: 0/3 en el perfil de laboratorio, se detiene en la etapa 1 (`raw/9bie-display-off-3run.txt`) | `NO ALCANZADO` | Sección 11 |
| mod_php 8.4.26 | `display_errors=Off` · ASLR On | Cadena de cookie: solo divulgación de heap con 4000 B (ventana de 1.88 MB), 0/3 RCE. Cadena 9bie anterior: 0/3 en el perfil de laboratorio, se detiene en la etapa 1 (`raw/9bie-display-off-3run.txt`); cadena `pure/` del upstream: **10/10** en stock 128M/150 workers con `display_errors=Off` y ASLR On (`raw/9bie-pure-off-aslr-on-10run.txt`), 0/5 en 8.4.27 | `NO ALCANZADO` | Sección 11 |
| FPM 8.4.26 (Leak) | FastCGI Stream · ASLR On | Worker muere en OOM (`exit 70`, 502); worker nuevo con heap limpio | `SIN CANAL` | Sección 10 |
| CVE-2026-115560 | `php_binary` + runtime `ini_set()` | Fallo de decode observado; sin impacto en seguridad de memoria | `NO CONCLUYENTE` | Sección 12 |
| Chunked `post_max_size` | Sin parche (8.2.34 / 8.3.35 / 8.4.26) | 30M parsea completo, 70M causa OOM en límite de 128M | `BYPASS CONFIRMADO` | Sección 12 |
Expand Down
Loading
Loading