Skip to content

Latest commit

 

History

History

exploit

Folders and files

NameName
Last commit message
Last commit date

parent directory

..
 
 
 
 
 
 
 
 

README.md

exploit/ — proving exploitability

Two pieces live here:

  • p2s_verify.py — the blind, no-artifact exploitability verifier (the safe default).
  • engine/ — the low-level use-after-free chain primitive the verifier drives (third-party, MIT; see the repository NOTICE). RedSide's dynamic-ASLR calibration is applied on top via php2shell-dynamic-aslr.patch.

For the one-command experience (fingerprint → offsets → check → optional HTTP-readback proof) use ../p2s.py instead. Use the pieces here when you want the blind check on its own, or to drive a target whose offsets you supply by hand.

Blind verification — p2s_verify.py

Confirms RCE without staging anything, sharing anything, or reading data back. It runs sleep N (7 bytes — it fits the 14-byte command carrier) through the chain and times the trigger request: a normal request is sub-second; if code executed, the destructor runs the sleep and the response is delayed ~N seconds. That delay is the proof.

# auto: fingerprint the version, pull offsets from ../real-vm/offsets_db.json, sweep htdata
python3 exploit/p2s_verify.py -u http://target/ --sleep 8

# manual: supply offsets for a build not in the database
python3 exploit/p2s_verify.py -u http://target/ \
    --zif-offset 0x.. --dtor-offset 0x.. --htdata-offset 0x..

Options: --sleep N (timing signal), --sweep K (htdata ±K page sweep per candidate), --retries N, --version X.Y.Z (skip fingerprint), --zif/--dtor/--htdata-offset.

Output on success: WORKED - RCE CONFIRMED: command executed (request delayed ~Ns) — and it names the build offsets that landed. No file, no exfil.

Dynamic ASLR calibration — php2shell-dynamic-aslr.patch

The raw chain filters leaked pointers against a hard-coded userspace window that only holds on hosts with 28-bit mmap entropy (e.g. Kali). On hosts with vm.mmap_rnd_bits=32 (Ubuntu 24.04 / kernel 6.8) PHP maps lower and every leak is discarded. The patch replaces the fixed window with a self-calibrating gate: it widens the pre-filter to a host-agnostic noise gate and lets the code discover the real base each run. No ASLR base is assumed and no host hardening is disabled.

p2s.py and p2s_verify.py apply this gate internally, so for the normal drivers you don't need to patch anything. The .patch file is provided for anyone driving engine/ directly:

git apply exploit/php2shell-dynamic-aslr.patch   # from a checkout of the engine

The 14-byte carrier

The command is embedded in a fixed 167-byte heap object that also holds a forged HashTable, execute_data, and string header; the command is the tail, capped at 14 bytes (167 − 0x98 − 1 NUL). sleep 8 fits directly. For a longer command, use a short loader such as sh</tmp/c (8 bytes) that reads an arbitrarily long staged script.