hardFreevulnerability-researchphpmemory-safetyuse-after-free
Course

PHP2Shell: From the Bug to the Shell

Two memory-safety vulnerabilities in the PHP engine, from the twenty-year-old primitive they came from to a shell on a service that carries the same bug.

14
Modules
33
Lectures
3
Hands-on labs
15h
Of material

About this course

Two memory-safety vulnerabilities in the PHP engine, from the twenty-year-old primitive they came from to a shell on a service that carries the same bug. On 21 October 2026 the PHP project released four versions at once. CVE-2026-109618 and CVE 2026-109619 both score 9.2, both need no account, and both are in the engine rather than in anybody's application. A page containing nothing but <?php echo "hello"; on an affected build is affected. There is no way to write your way out of it. This course is about how those bugs were found, triaged and root caused, how a defender finds and stops them, and how the same pattern is taken to command execution. The engine CVEs are studied, not attacked: no live site is touched and no exploit is built against the released engine. The last three modules build a full chain instead against a small service the course plants, which carries one instance of the same pattern on purpose, so the method is taught end to end against a target that is ours. You work on the real thing throughout. The research lab carries the released source of 8.3.35 and 8.3.36, built four ways, plus a fifth build of the fuzzer harnesses and a read-only copy of both releases, so every claim in a lecture is a file you can open. The fix between those two tags touches over four hundred paths, and module 8 reads it. The crash you triage in module 5 is a real interruption in a function every PHP request runs thousands of times, and the six lines that cause it are upstream code, not an exercise. One pattern runs through the whole course. Publish or destroy state, do fallible work, then commit or restore. If a non-local exit fires during the fallible work, the last step never runs and a later consumer trusts the false state. That shape is what turned one finding into four, it is what the official fix is designed around, and it is the bug in the planted service you take to a shell at the end. The instrument is allocation failure injection. Rather than guessing which input breaks the engine, you choose which allocation fails and watch what the engine does next. That makes a class of bug that is usually described in prose into something you can sweep, tabulate and compare between a vulnerable build and a patched one. Both server interfaces are covered, because they do not behave the same way. A fatal during request startup under Apache with modphp leaves the worker alive and reusing broken state. The same failure under PHP-FPM takes the worker out. That difference decides which primitives matter where, and module 7 makes you watch both. The middle third is defensive work and it is graded by execution. You write detections for the request shapes that precede the fatal, run them against traffic that contains both an attack and an ordinary afternoon, and measure what you caught and what you woke somebody up for. Then you apply the real mitigations, per interface and per CVE, and verify them instead of asserting them. The last third is the chain. Against the planted service you reclaim a freed table with one allocation, read a length of your own out of it, defeat address randomization from a single leak, and turn a cast into a command that runs as the service account. Then you patch the service so the whole chain fails, checked by a verifier that will not accept a fix that breaks what the service does.

Syllabus

14 modules, 33 lectures, 11 quizzes and 3 hands-on challenges.

  1. Module 0: PHP2Shell in Context

    Two CVEs, one changelog entry, and a boundary. What the bugs are, when the world found out, what the models did and did not do, and where this course stops.

    • PHP2Shell: two CVEs in the engine
    • The disclosure timeline, and the question about the model
    • Course scope, and how to check the facts in it

    1 quiz

  2. Module 1: Vulnerability Archaeology

    The same primitive in 2004, 2020, 2024 and 2026. Why a target's history is a discovery technique, and how to build the catalogue that aims one.

    • A twenty-two year lineage
    • Building a vulnerability catalogue for a target

    1 quiz

  3. Module 2: PHP Engine Internals

    The request lifecycle, the request heap, the globals that outlive a request, and the non-local jump that skips a commit. Everything after this module is an application of these four lectures.

    • SAPIs and the request lifecycle
    • The Zend Memory Manager and the request heap
    • Executor, compiler and module globals
    • Fatal errors, zend_bailout and the interruption pattern

    1 quiz

  4. Module 3: Building PHP for Research

    A build you can trust, a memory checker that can see the engine's allocations, and the three link failures that carry no useful message.

    • Configuring php-src for research
    • Memory checkers for the engine

    1 quiz

  5. Module 4: Finding the Bug

    A fuzzing campaign that cannot reach this class, an instrument that can, and the distillation step that turns one finding into a hunt.

    • Coverage-guided fuzzing with the in-tree harnesses
    • Allocation failure injection
    • Pattern distillation and variant hunting

    1 quiz

  6. Module 5: Crash Triage and Root Cause

    Name the object, the stale reference and the window. Then read the six lines of upstream code that the whole course is about.

    • Reading a use-after-free report
    • The six lines in zend_hash.c

    1 quiz

  7. Module 6: The Four Primitives

    Each reported primitive, mapped to its engine code path and its affected server interface. Including the one that does not exist in this branch at all.

    • The SAPI pivot
    • Request variables and HashTable teardown
    • Session upload progress and the dangling globals
    • Serializer bookkeeping after startup
    • OPcache slot publishing, and the backtrace path

    1 quiz

  8. Module 7: Observing the Symptoms

    Three server interfaces, one injected failure, and the table that shows a worker surviving a fatal and refusing every request afterwards.

    • Worker reuse and the two failure windows

    1 quiz

  9. Module 8: Reading the Fix

    Four hundred and thirty paths, one new idea, and the five lines somebody deciding about Friday actually needs.

    • Fallible allocation and delayed out of memory
    • Reading a security diff

    1 quiz

  10. Module 9: Detection Engineering

    The request shapes that arrive before the fatal, the response header that carries the disclosure, and a runbook for the morning after. Graded by measurement rather than by a model answer.

    • The request shapes that precede the fatal
    • Response-side signals, and the incident response runbook

    1 quiz

  11. Module 10: Mitigation and Verification

    The one complete fix, the stopgaps and what each costs, the directive form an application cannot override, and the two tables that make a verification.

    • Mitigations, per interface and per record, and how to verify one

    1 quiz

  12. Module 11: The Target

    A small PHP service built on the course's own pattern, the rule that makes its heap repeat, and the one allocation that reclaims a freed table.

    • A service built on the pattern
    • The rule that makes an address repeat

    1 hands-on challenge

  13. Module 12: To a Shell

    The released block reclaimed and read, two addresses out of one read, and a call frame that turns a cast into a command.

    • Reclaiming the block, and reading out of it
    • Two addresses from one read
    • The call, and a command

    1 hands-on challenge

  14. Module 13: Closing the Window

    The fix that makes the whole chain fail, two ways to write it, and a verifier that will not accept a fix that breaks the service.

    • Closing the window

    1 hands-on challenge

14 modules about 15 hoursOpened from your Arena account

Take PHP2Shell: From the Bug to the Shell

Create an account to open the lectures and launch this course's labs in the browser.

Create a free account