From 719ebe0d92587878566e33f5dd06fec0114f5fc3 Mon Sep 17 00:00:00 2001 From: JoshRob Date: Mon, 9 Nov 2026 22:15:20 -0600 Subject: [PATCH] 1.13.0: chain E layout, reliability, and the sweep that was not one --- CHAIN-E.es.md | 110 ++++++++++++++++++++++++++++ CHAIN-E.md | 108 ++++++++++++++++++++++++++++ README.es.md | 4 +- README.md | 6 +- RELIABILITY.es.md | 61 ++++++++++++++++ RELIABILITY.md | 58 +++++++++++++++ raw/chain-e-aslr-sweep-387.txt | 127 +++++++++++++++++++++++++++++++++ 7 files changed, 469 insertions(+), 5 deletions(-) create mode 100644 CHAIN-E.es.md create mode 100644 CHAIN-E.md create mode 100644 RELIABILITY.es.md create mode 100644 RELIABILITY.md create mode 100644 raw/chain-e-aslr-sweep-387.txt diff --git a/CHAIN-E.es.md b/CHAIN-E.es.md new file mode 100644 index 0000000..f02c6e8 --- /dev/null +++ b/CHAIN-E.es.md @@ -0,0 +1,110 @@ +# Cadena E — la ruta FPM, medida +[English](CHAIN-E.md) · [Español](CHAIN-E.es.md) + + +La cadena E es el brazo PHP-FPM del primitivo E-OOM: un fallo de memoria al deserializar deja +`BG(unserialize)` en `level=1` con el puntero `data` colgando, el siguiente decode lo reutiliza, +y una escritura controlada de 16 bytes aterriza en `&sapi_module.ub_write`, que se sustituye por +`&system`. + +**Es un resultado de laboratorio, no una capacidad remota.** Bajo ASLR por defecto es una +denegación de servicio determinista (caída del worker, 502). La ejecución de comandos exige ASLR +apagado o bases ya conocidas, más una sesión plantada de 24 bytes. Todo lo de abajo es lo que +medimos, incluidas las rutas que no funcionaron. + +Este documento publica el layout y los números. No publica el orquestador: el código que +tenemos es un fragmento que no corre sin nuestro arnés, y uno de sus constructores acepta una +dirección que nunca usa. Publicarlo como "cadena pública" sería publicar algo que no corre. + +## La escritura + +Un `var_dtor_entries` falso vive en el buffer de un campo multipart. El bucle del destructor lo +recorre y escribe una entrada por iteración, así que el desplazamiento de aterrizaje lo fija el +conteo de entradas: + +``` +T2 = d + 0x110 + 16·N N = (T2 − d − 0x110) / 16 +``` + +`T2` es `&sapi_module.ub_write`. `d` es la dirección del struct reclamado. Si +`(T2 − d − 0x110)` no es múltiplo de 16, la cadena no puede aterrizar: el constructor falla en +vez de desalinear en silencio. + +Desplazamientos dentro del buffer falso de 12,300 bytes, medidos: + +- `0x1000` — `entries.last` = `d + 0x38` +- `0x1008` — `entries.first_dtor` = `0` +- `0x1010` — `last_dtor` = `d + 0x100` +- `0x1038` — `entries.used_slots` = `0` +- `0x1100` — `fake.used_slots` = `N` +- `0x1108` — `fake.next` = `0` + +## La sesión plantada: 24 bytes, y el contenido importa + +La sesión debe medir **exactamente 24 bytes**, con la forma: + +``` +C|i:;AAAA +``` + +Los dos hechos están medidos, no supuestos: + +- `hello|i:;` —también 24 bytes— **rompió el layout**. El arena de strings internados corrompe + el struct `d` antes de la escritura, y el proceso muere con SEGV en `tmp_var` (solo visible + con `WATCH`). +- La cola `AAAA` dispara un `cancel_decode` benigno. La escritura ya ocurrió en el primer par, + así que el aviso es cosmético. + +## La desincronización posterior al exec + +Secuestrar `ub_write` rompe el contrato de salida del motor. PHP espera que `ub_write` devuelva +el número de bytes escritos; `system()` devuelve el estado de salida de la subshell, así que la +capa SAPI ve `rax = 0`, llama a `php_handle_aborted_connection` y el cliente recibe un 502. + +El payload tiene que desacoplar: `foo; (cmd; kill -TERM $$) >/dev/null 2>&1 &`. El comando corre +en una subshell, el worker dañado se recicla y la respuesta puede morir. + +## Rutas que no funcionaron + +Todas fueron medidas y cerradas: + +- **`PS(serializer)->decode = &system`** — la escritura aplasta `http_session_vars` en `+8`, da + `Z_REFVAL(0x4)` y SEGV antes del segundo decode. +- **`GOT(memchr)` = `0x1600c38`** — `mod 16 = 8`, inalcanzable con slots alineados a 16. +- **Gadget `lea/mov 0x18(%rcx),%rdi; jmp exec`** — no existe en el binario. Tampoco importa + `system`: solo `popen` / `posix_spawn` / `fork`, y `popen` exige un modo válido en `rsi`. +- **Regla re2c `"i:" iv ";"`** — verificada en fuente: el `;` es parte de la regla. `i:` sin + `;` no escribe el LONG. +- **Barrido de páginas ASLR** — ver abajo. No existe como mecanismo en nuestras herramientas. + +## El barrido, medido + +Teníamos un módulo llamado `aslr_sweep`, descrito como barrido determinista de páginas para FPM +remoto. Valía la pena comprobarlo, porque si funcionaba el veredicto `LAB ONLY` estaba mal. + +No funciona, y estructuralmente no puede: la petición que envía es `{"page": N}` como form data, +sin cuerpo forjado y sin aritmética de direcciones. Nunca intenta un aterrizaje. + +Peor: su criterio de éxito coincidía con `"OK"` en el cuerpo de la respuesta +independientemente del `marker` que se le pasara, así que contra una página que imprime `OK` +reporta éxito en la página 0. + +Medido el 2026-11-09, `phpdebug:8.4.26-fpm` con `pm = static`, un worker, detrás de nginx, +`randomize_va_space = 2`: + +- con el criterio del propio código: `success = True`, página 0, 0.01 s, una petición — falso + positivo, nada se ejecutó +- con criterio estricto (`uid=` y `gid=` obligatorios): **387 páginas, 387 respuestas 200, 0 + aciertos, 0.34 s, 0 caídas**, la página sigue sirviendo, ningún payload construido + +Transcripción: [`raw/chain-e-aslr-sweep-387.txt`](raw/chain-e-aslr-sweep-387.txt). + +## Qué significa + +`LAB ONLY` se sostiene, y ahora está cerrado por los dos lados: el bloqueo de fragmentación +bin-16 que ya teníamos, y la ausencia de cualquier barrido que lo sortee. + +Si estás leyendo esto para reproducir: necesitas ASLR apagado o bases conocidas, una sesión de +exactamente 24 bytes con la forma de arriba plantada bajo el id de la víctima, una página que +llame a `session_start()`, y un worker que no se recicle entre las dos peticiones. Sin las +cuatro, esto es un 502. diff --git a/CHAIN-E.md b/CHAIN-E.md new file mode 100644 index 0000000..3f601a1 --- /dev/null +++ b/CHAIN-E.md @@ -0,0 +1,108 @@ +# Chain E — the FPM path, measured +[English](CHAIN-E.md) · [Español](CHAIN-E.es.md) + + +Chain E is the PHP-FPM arm of the E-OOM primitive: a decode out-of-memory leaves +`BG(unserialize)` at `level=1` with a dangling `data` pointer, the next decode reuses it, and a +controlled 16-byte write lands on `&sapi_module.ub_write`, which is replaced with `&system`. + +**It is a lab result, not a remote capability.** Under default ASLR it is a deterministic +denial of service (worker crash, 502). Command execution requires ASLR off or already-known +bases, plus a planted 24-byte session. Everything below is what we measured, including the +paths that did not work. + +This document publishes the layout and the numbers. It does not publish the orchestrator: the +code we have is a fragment that cannot run without our harness, and one of its builders accepts +an address it never uses. Shipping that as a "public chain" would be shipping something that +does not run. + +## The write + +A fake `var_dtor_entries` sits in a multipart field buffer. The destructor loop walks it and +writes one entry per iteration, so the landing offset is set by the entry count: + +``` +T2 = d + 0x110 + 16·N N = (T2 − d − 0x110) / 16 +``` + +`T2` is `&sapi_module.ub_write`. `d` is the address of the reclaimed struct. If +`(T2 − d − 0x110)` is not a multiple of 16 the chain cannot land at all — the builder refuses +rather than silently misaligning. + +Field offsets inside the 12,300-byte fake entries buffer, as measured: + +- `0x1000` — `entries.last` = `d + 0x38` +- `0x1008` — `entries.first_dtor` = `0` +- `0x1010` — `last_dtor` = `d + 0x100` +- `0x1038` — `entries.used_slots` = `0` +- `0x1100` — `fake.used_slots` = `N` +- `0x1108` — `fake.next` = `0` + +## The planted session: 24 bytes, and the contents matter + +The session must be **exactly 24 bytes**, of the form: + +``` +C|i:;AAAA +``` + +Both facts are measured, not assumed: + +- `hello|i:;` — also 24 bytes — **broke the layout**. The interned-strings arena corrupts + struct `d` before the write, and the process dies with SEGV in `tmp_var` (only visible under + `WATCH`). +- The trailing `AAAA` triggers a benign `cancel_decode` warning. The write has already happened + in the first pair, so the warning is cosmetic. + +## The post-exec desynchronisation + +Hijacking `ub_write` breaks the engine's output contract. PHP expects `ub_write` to return the +number of bytes written; `system()` returns the subshell's exit status, so the SAPI layer sees +`rax = 0`, calls `php_handle_aborted_connection`, and the client gets a 502. + +The payload has to decouple: `foo; (cmd; kill -TERM $$) >/dev/null 2>&1 &`. The command runs in +a subshell, the damaged worker is recycled, and the response is allowed to die. + +## Paths that did not work + +Each of these was measured and closed: + +- **`PS(serializer)->decode = &system`** — the write crushes the neighbouring `http_session_vars` + at `+8`, giving `Z_REFVAL(0x4)` and a SEGV before the second decode. +- **`GOT(memchr)` = `0x1600c38`** — `mod 16 = 8`, unreachable with 16-byte-aligned slots. +- **Gadget `lea/mov 0x18(%rcx),%rdi; jmp exec`** — does not exist in the binary. It does not + import `system` either, only `popen` / `posix_spawn` / `fork`, and `popen` needs a valid mode + string in `rsi`. +- **re2c rule `"i:" iv ";"`** — verified in source: the `;` is part of the rule. `i:` without + `;` does not write the LONG at all. +- **ASLR page sweep** — see below. It does not exist as a mechanism in our tooling. + +## The sweep, measured + +We had a module called `aslr_sweep` described as a deterministic page sweep for remote FPM. It +was worth checking, because if it worked, the `LAB ONLY` verdict would be wrong. + +It does not work, and structurally cannot: the request it sends is `{"page": N}` as form data, +with no forged body and no address arithmetic. It never attempts a landing. + +Worse, its success check matched `"OK"` in the response body regardless of any marker passed in, +so against a page that prints `OK` it reports success on page 0. + +Measured on 2026-11-09, `phpdebug:8.4.26-fpm` with `pm = static`, one worker, behind nginx, +`randomize_va_space = 2`: + +- with the code's own criterion: `success = True`, page 0, 0.01 s, one request — a false + positive, nothing executed +- with a strict criterion (`uid=` and `gid=` required): **387 pages, 387 responses 200, 0 hits, + 0.34 s, 0 crashes**, page still serving, no payload ever built + +Transcript: [`raw/chain-e-aslr-sweep-387.txt`](raw/chain-e-aslr-sweep-387.txt). + +## What this means + +`LAB ONLY` stands, and now it is closed from both sides: the bin-16 fragmentation blocker we +already had, and the absence of any sweep that bypasses it. + +If you are reading this to reproduce: you need ASLR off or known bases, a session of exactly +24 bytes in the shape above planted under the victim's id, a page that calls `session_start()`, +and a worker that does not recycle between the two requests. Without all four, this is a 502. diff --git a/README.es.md b/README.es.md index 7677080..fab7ec4 100644 --- a/README.es.md +++ b/README.es.md @@ -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.12.0_(2026--11--09)-0284c7?style=flat-square&logo=github)](https://github.com/JoshRob297/php2shell-research/releases/tag/v1.12.0) +[![Release](https://img.shields.io/badge/Release-v1.13.0_(2026--11--09)-0284c7?style=flat-square&logo=github)](https://github.com/JoshRob297/php2shell-research/releases/tag/v1.13.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)](#) @@ -22,7 +22,7 @@ Contacto: Telegram [@JocesLab](https://t.me/JocesLab) · correo [joshrob.sec@pro - **Estado**: Publicación v1.9.2, 2026-11-09 (verificación del estado de parches contra php.net y php-src, más el puntero de v1.0.0 a la última; calibración en imágenes oficiales de distribución, pruebas de aislamiento de stdout en FastCGI, desambiguación de arquitecturas SAPI, alcance de ASLR medido por tamaño de lectura, transcripciones por corrida de la cadena 9bie y arnés de medición publicado). - **Alcance**: Ramas de PHP 8.4.x y adyacentes (8.2, 8.3, 8.5), imágenes oficiales en contenedores, código público de prueba de concepto (PoC) y reproducción independiente en laboratorio. - **Alcance aplicativo**: Se utilizó un entorno de prueba de Nextcloud 33.0.x (PHP 8.4.21, Apache `mod_php` prefork) para validar la exposición de configuración y nivel de parche. La prueba de RCE se obtuvo sobre la imagen oficial `php:8.4.26-apache`. El fallo reside en el inicio de la petición de PHP, no en el código de Nextcloud. -- **Artefactos**: `PORTABILITY.es.md` (la matriz medida de qué condiciona la cadena), `TIMELINE.es.md` (cronología de la divulgación con fuentes), versiones formales en PDF (`REPORT.pdf` y `RESUMEN.pdf`), instrumentación de laboratorio reproducible (`tooling/labkit/` y `tooling/docker-compose.yml`), herramienta de diagnóstico no destructiva (`tooling/checker/`), calculadoras offline de alcanzabilidad y reglas de detección. +- **Artefactos**: `PORTABILITY.es.md` (la matriz medida de qué condiciona la cadena), `TIMELINE.es.md` (cronología de la divulgación con fuentes), `CHAIN-E.es.md` (el brazo FPM, medido: layout, precondiciones y las rutas que no funcionaron), `RELIABILITY.es.md` (qué decide si dispara, y con qué frecuencia), versiones formales en PDF (`REPORT.pdf` y `RESUMEN.pdf`), instrumentación de laboratorio reproducible (`tooling/labkit/` y `tooling/docker-compose.yml`), herramienta de diagnóstico no destructiva (`tooling/checker/`), calculadoras offline de alcanzabilidad y reglas de detección. - **Asistencia de IA**: Se utilizaron múltiples modelos de IA y subagentes especializados bajo dirección humana para revisión, orquestación de laboratorio y comprobación documental; cada hallazgo fue contrastado contra comandos, salidas reales o fuentes públicas. Ver `METHODOLOGY.md`. --- diff --git a/README.md b/README.md index acbafa8..fac33dc 100644 --- a/README.md +++ b/README.md @@ -3,7 +3,7 @@ # php2shell — Independent Verification & Exploitation Boundary Audit ### CVE-2026-109618 · CVE-2026-109619 · CVE-2026-115560 -[![Release](https://img.shields.io/badge/Release-v1.12.0_(2026--11--09)-0284c7?style=flat-square&logo=github)](https://github.com/JoshRob297/php2shell-research/releases/tag/v1.12.0) +[![Release](https://img.shields.io/badge/Release-v1.13.0_(2026--11--09)-0284c7?style=flat-square&logo=github)](https://github.com/JoshRob297/php2shell-research/releases/tag/v1.13.0) [![Target](https://img.shields.io/badge/PHP_Targets-8.2_·_8.3_·_8.4_·_8.5-334155?style=flat-square)](#) [![CVSS](https://img.shields.io/badge/CVSS_v4.0-9.2_CRITICAL-b91c1c?style=flat-square)](#) [![ASLR](https://img.shields.io/badge/ASLR-Cookie_Window_1.88_MB-d97706?style=flat-square)](#) @@ -19,10 +19,10 @@ Contact: Telegram [@JocesLab](https://t.me/JocesLab) · email [joshrob.sec@proto --- -- **Status**: public release v1.12.0, 2026-11-09 (portability matrix and disclosure timeline published, patch-state check against php.net and php-src, plus the v1.0.0→latest pointer; official stock distribution image calibration, FastCGI stdout isolation proofs, SAPI architecture disambiguation, measured ASLR scope per read size, per-run 9bie transcripts, and the published measurement harness). +- **Status**: public release v1.13.0, 2026-11-09 (portability matrix and disclosure timeline published, patch-state check against php.net and php-src, plus the v1.0.0→latest pointer; official stock distribution image calibration, FastCGI stdout isolation proofs, SAPI architecture disambiguation, measured ASLR scope per read size, per-run 9bie transcripts, and the published measurement harness). - **Scope**: PHP 8.4.x and adjacent branches (8.2, 8.3, 8.5), official PHP container images, public proof-of-concept code, and independent lab reproduction. - **Application scope**: a Nextcloud 33.0.x test deployment (PHP 8.4.21, Apache `mod_php` prefork) was used to validate the exposed configuration and patch level. The RCE proof was obtained on the official `php:8.4.26-apache` image. The bug is in PHP request startup, not Nextcloud code. -- **Artifacts**: `PORTABILITY.md` (the measured matrix of what gates the chain), `TIMELINE.md` (disclosure timeline with sources), formal typography PDF releases (`REPORT.pdf` and `RESUMEN.pdf`), reproducible lab instrumentation (`tooling/labkit/` and `tooling/docker-compose.yml`), non-destructive diagnostic tooling (`tooling/checker/`), offline reachability calculators, and detection rules. +- **Artifacts**: `PORTABILITY.md` (the measured matrix of what gates the chain), `TIMELINE.md` (disclosure timeline with sources), `CHAIN-E.md` (the FPM arm, measured: layout, preconditions and the paths that did not work), `RELIABILITY.md` (what decides whether it fires, and how often), formal typography PDF releases (`REPORT.pdf` and `RESUMEN.pdf`), reproducible lab instrumentation (`tooling/labkit/` and `tooling/docker-compose.yml`), non-destructive diagnostic tooling (`tooling/checker/`), offline reachability calculators, and detection rules. - **AI-assisted**: multiple AI models and specialized subagents were used under human direction for review, lab orchestration and documentation checks; every finding was validated against commands, outputs or public sources. See `METHODOLOGY.md`. ## Executive summary diff --git a/RELIABILITY.es.md b/RELIABILITY.es.md new file mode 100644 index 0000000..e0c9897 --- /dev/null +++ b/RELIABILITY.es.md @@ -0,0 +1,61 @@ +# Fiabilidad — cuántas veces dispara de verdad +[English](RELIABILITY.md) · [Español](RELIABILITY.es.md) + + +Una corrida exitosa no es un resultado. Estas son las condiciones que deciden si la cadena con +`display_errors=Off` y ASLR encendido dispara o no, y con qué frecuencia, medidas sobre targets +nuevos. + +## Geometría: 128M y `php.ini-production`, o nada + +La cadena `pure/` del upstream está calibrada para la geometría stock: `memory_limit=128M`, el +`php.ini-production` oficial y el pool de workers tal como lo trae la imagen. + +- 128M, un worker, imagen oficial → **3/3** +- 8M, un worker, misma imagen → **0/3** + +El fallo a 8M es **calibración, no el disparador**. A1 sí dispara a 8M: nuestra cadena anterior +da **8/8** ahí con `display_errors=On` (ver `PORTABILITY.es.md`). Lo que se rompe son la +aritmética de offsets y la ventana del leak, ambas dimensionadas para la arena de 128M. + +Esto importa porque circula la frase de que bajar `memory_limit` no ayuda, porque el atacante +dimensiona el OOM al límite que haya. **Las dos afirmaciones son ciertas y hablan de cadenas +distintas.** En la cadena de cookie de mod_php el atacante elige el tamaño del cuerpo y el +límite no lo frena. En la cadena `pure/` del upstream las constantes están fijas para 128M, así +que un target de 8M falla por una razón que no tiene nada que ver con el control del cuerpo. + +## El `php.ini` del target decide más que la versión + +Nuestro propio `tooling/docker-compose.yml` **no** reproduce el 10/10. El servicio `vuln-8426` no +carga ningún `php.ini`: + +``` +Loaded Configuration File => (none) +display_errors => STDOUT +``` + +Añadir `display_errors=Off` encima de `hardening-off.ini` da **0/3**, porque eso es un overlay de +`conf.d`, no `php.ini-production`. La cadena necesita el archivo que trae la imagen, no una +directiva que se le parezca. + +## El arranque en frío no está caracterizado + +Target nuevo, primera corrida: **0/3**, con `no heap pointers in leak window`. El mismo target +tras `docker restart`: **3/3**. El resultado de diez corridas en +`raw/9bie-pure-off-aslr-on-10run.txt` reinicia el target antes de cada corrida exactamente por +esto. + +No hemos caracterizado el fallo de la primera corrida: puede ser calentamiento del pool, estado +del allocator o residencia de páginas. Es una incógnita conocida, escrita en vez de promediada. + +## Lo que no está medido + +- **FPM**: el brazo E-OOM es `LAB ONLY` y está en `CHAIN-E.es.md`. Sin resultado remoto con ASLR + encendido. +- **CVE-2026-115560**: sin arreglo estable al momento de escribir; nuestro intento fue + inconcluso. +- **Carga sostenida**: todas las corridas son de segundos a minutos. Nada de aquí dice nada sobre + el comportamiento tras horas de carga. + +Si un número de este repositorio no está en este archivo ni en una transcripción de `raw/`, no es +una medición: es una cita. diff --git a/RELIABILITY.md b/RELIABILITY.md new file mode 100644 index 0000000..93b2ff8 --- /dev/null +++ b/RELIABILITY.md @@ -0,0 +1,58 @@ +# Reliability — how often it actually fires +[English](RELIABILITY.md) · [Español](RELIABILITY.es.md) + + +A single successful run is not a result. These are the conditions that decide whether the +`display_errors=Off` + ASLR-on chain fires at all, and how often, measured across fresh targets. + +## Geometry: 128M and `php.ini-production`, or nothing + +The upstream `pure/` chain is calibrated for the stock geometry: `memory_limit=128M`, the +official `php.ini-production`, and the prefork worker pool as the image ships it. + +- 128M, one worker, official image → **3/3** +- 8M, one worker, same image → **0/3** + +The failure at 8M is **calibration, not the trigger**. A1 does fire at 8M — our older chain goes +**8/8** there with `display_errors=On` (see `PORTABILITY.md`). What breaks is the offset +arithmetic and the leak window, both sized for the 128M arena. + +This matters because a widely quoted sentence says that lowering `memory_limit` does not help, +because the attacker sizes the OOM request to whatever the limit is. **Both statements are +true and they are about different chains.** In the mod_php cookie chain, the attacker picks the +body size and the limit does not stop them. In the upstream `pure/` chain, the constants are +fixed for 128M, so an 8M target fails for a reason that has nothing to do with the attacker's +control over the body. + +## The target's `php.ini` decides more than the version + +Our own `tooling/docker-compose.yml` does not reproduce the 10/10. The service `vuln-8426` loads +no `php.ini` at all: + +``` +Loaded Configuration File => (none) +display_errors => STDOUT +``` + +Adding `display_errors=Off` on top of `hardening-off.ini` gives **0/3**, because that is a +`conf.d` overlay, not `php.ini-production`. The chain needs the file the image ships with, not +an equivalent-looking directive. + +## Cold start is not characterised + +A fresh target, first run: **0/3**, with `no heap pointers in leak window`. The same target after +`docker restart`: **3/3**. The ten-run result in `raw/9bie-pure-off-aslr-on-10run.txt` restarts +the target before every run for exactly this reason. + +We have not characterised the first-run failure: it could be pool warm-up, allocator state, or +page residency. It is a known unknown, written down instead of averaged away. + +## What is not measured + +- **FPM**: the E-OOM arm is `LAB ONLY` and is covered in `CHAIN-E.md`. No remote ASLR-on result. +- **CVE-2026-115560**: no stable fix at the time of writing; our attempt was inconclusive. +- **Long-running soak**: all runs are seconds-to-minutes. Nothing here says anything about + behaviour after hours of load. + +If a number in this repository is not in this file or in a `raw/` transcript, it is not a +measurement. It is a citation. diff --git a/raw/chain-e-aslr-sweep-387.txt b/raw/chain-e-aslr-sweep-387.txt new file mode 100644 index 0000000..819113c --- /dev/null +++ b/raw/chain-e-aslr-sweep-387.txt @@ -0,0 +1,127 @@ +chain-e / aslr_sweep — medición del 2026-11-09 +============================================== + +Pregunta: ¿el módulo `aslr_sweep` derrota ASLR lo suficiente como para que la cadena E deje de +ser LAB ONLY? + +Respuesta: no. No construye payload, y su criterio de éxito da falso positivo con "OK". + +Target +------ +Host cachy, kernel con randomize_va_space = 2 (ASLR encendido) +fpmdbg phpdebug:8.4.26-fpm pm = static, pm.max_children = 1, listen 9000 +ngdbg nginx:alpine 127.0.0.1:18088 -> fpmdbg:9000 +webroot index.php: +