The opt-in active check now recognizes a pre-fix PHP session code path without executing code or reading session data. Two small invalid-session multipart requests must independently produce the extra PHP session-write warning. This pattern makes the user-facing result Vulnerable in the absence of conflicting patch evidence. It indicates an unpatched path, not proven remote code execution or a demonstration of memory corruption.
No universal remote observable was established from the reviewed primary
advisories and regression tests, even after allowing a bounded worker crash.
This does not make a crash an oracle. A memory-corruption trigger
can disrupt other requests even without RCE; worker death, generic errors or
timeouts alone cannot establish either CVE. See ACTIVE_CHECK_RESEARCH.md for
the crash-permitted re-review and local OOM control.
Official Windows NTS x64 releases were downloaded over HTTPS from
downloads.php.net/~windows/releases/archives/. SHA-256 values recorded for the
downloaded archives (provenance records, not a claim of signature verification):
| Build | SHA-256 |
|---|---|
| 8.4.26 | da68394f9193b7f6b89d0c76861a4034ae10efee7fd55a7255d8118c2acf70d7 |
| 8.4.27 | 93bd8a815a52156606fb906d0573437908c61f96e2cc52c03a51e36a41bf5236 |
Each PHP CLI development server listened only on 127.0.0.1. The test app served
a static PHP baseline and a local phpinfo page. Each version was checked with
display_errors and session.upload_progress.enabled on/off: eight configurations.
| PHP | display_errors | upload_progress | Rejected SID warning | OOM patch feature |
|---|---|---|---|---|
| 8.4.26 | Off | Off | No | Absent |
| 8.4.26 | Off | On | No | Absent |
| 8.4.26 | On | Off | No | Absent |
| 8.4.26 | On | On | Yes | Absent |
| 8.4.27 | Off | Off | No | Present |
| 8.4.27 | Off | On | No | Present |
| 8.4.27 | On | Off | No | Present |
| 8.4.27 | On | On | Yes | Present |
The single session-ID warning failed specificity: both pre-fix and fixed PHP produced it. The new check looks for the additional session-write warning, which appears only before the fix in the matched lab. Both warning types and their ordering are checked; repeating the request reduces transient errors.
The production active collector was run against four official pre-fix/fixed
pairs: 8.2.34/35, 8.3.35/36, 8.4.26/27 and 8.5.11/12. All eight builds
returned the expected UNPATCHED_SESSION_PATH or PATCHED_SESSION_PATH
status. The full matrix covered 64 local configurations: two warning-display
settings, two session-ID placements and two upload-progress settings per build.
With display_errors off or upload progress disabled the warnings were
not visible, so a remote scan must remain inconclusive. The comparisons use
Windows CLI servers on localhost; Apache, FPM, proxy rewriting and vendor
backports were not independently validated.
A separate 16-configuration local comparison of official PHP 7.4.33 and
8.1.34 found no visible invalid-session warning on 7.4.33. PHP 8.1.34 printed
the three phrases with an older Unknown: prefix, which the 8.2–8.5 oracle
does not mistake for a patched result. There is no matched vendor-backported
8.1 control, so this legacy format is not promoted to Vulnerable.
An authorized production WordPress comparison found that / concealed the
warning pattern while /wp-login.php displayed the post-fix two-warning
pattern twice. Radar now tries that dynamic path after a silent WordPress front
page, before bounded memory probes. This gives another observable path, but
the two-warning result alone does not verify the installed package or all
workers. The production comparison stored only response status, warning shape,
and short header metadata; it saved no body or cookie values.
Structured phpinfo output reported memory_hard_limit_percent only in 8.4.27,
including a no value default in both local/master columns. This validates the
feature fingerprint on these two builds, not exploitation, full remediation,
backports, Apache mod_php, FPM, CGI, other branches or other operating systems.
Feature presence and reported version are separate pieces of evidence. The
structured page parser also extracted the matching version from every one of
the eight local controls. The engine uses that version only when it does not
conflict with passive HTTP evidence.
.venv\Scripts\python.exe scripts/fetch_php_lab.py
.venv\Scripts\python.exe scripts/validate_php_lab.pyDownloads and generated test apps stay under ignored artifacts/php-lab/. Each
server is terminated in a finally block. The validation script asserts the
expected comparison and writes its full report to artifacts/php-lab/validation.json.
The production opt-in active collector first sends one or two small session
requests. It also uses this small check on reached sites without passive PHP
evidence; a repeated supported-branch warning pattern can reveal hidden PHP.
An HTTP error status does not hide a complete warning pattern. This broader
coverage has offline mocked-response tests, but was not part of the matched
PHP build matrix above. Only sites already identified as PHP may receive three
bounded multipart memory-pressure requests if the small check is inconclusive.
They are globally serialized and stop on the first anomaly.
Run scripts/validate_bounded_oom_lab.py for a localhost-only comparison of
those exact bodies against 8.4.26 and 8.4.27. See
ACTIVE_CHECK_RESEARCH.md for its observations and why OOM alone cannot give a
direct CVE verdict. A single SID warning remains insufficient; the
additional session-write warning is the discriminating signal.
Run scripts/validate_session_warning_oracle.py --quick 8.2.34 8.2.35 8.3.35 8.3.36 8.4.26 8.4.27 8.5.11 8.5.12
after downloading those local builds to reproduce the complete collector
comparison. The JSON record is artifacts/php-lab/session-warning-oracle.json.
- Map its observable to the affected lifetime/OOM operation in official source.
- Reproduce on matched pre/post-patch builds with identical configuration.
- Show the signal disappears with the specific fix, not just with hidden errors, disabled uploads, a different pool or WAF behavior.
- Treat both CVEs separately. Include mod_php and FPM paths, multiple workers, different PHP branches and vendor backports before broad applicability claims.
- Send no attacker PHP, OS command, shell, gadget chain or data-extraction payload.
- Measure worker/process effects. A crash is not a sufficient generic oracle.
- Preserve
INCONCLUSIVEwhen the required path/observable cannot be established.