đ Contexte
PubliĂ© le 2 mai 2026 sur le blog de Calif (blog.calif.io), cet article technique dĂ©taille la dĂ©couverte et l’exploitation d’une vulnĂ©rabilitĂ© use-after-free (UAF) dans la fonction unserialize() de PHP, prĂ©sente depuis PHP 5.1 (2005) et toujours exploitable dans PHP 8.5.5. La dĂ©couverte s’inscrit dans le cadre du projet MAD Bugs (Month of AI-Discovered Bugs), combinant modĂšles d’IA (Claude) et expertise humaine.
đ La vulnĂ©rabilitĂ©
Le bug rĂ©side dans zend_user_unserialize() (fichier Zend/zend_interfaces.c), le point de dispatch pour Serializable::unserialize(). Contrairement Ă tous les autres points de dispatch utilisateur (__wakeup, __unserialize, __destruct), cette fonction omet d’incrĂ©menter BG(serialize_lock), ce qui permet Ă un appel rĂ©cursif Ă unserialize() de partager le var_hash externe.
- Les zvals de propriĂ©tĂ©s parsĂ©es en interne sont enregistrĂ©es comme slots externes, pointant vers l’
arDatade l’objet interne - Si l’objet est mutĂ© suffisamment pour dĂ©clencher un redimensionnement de la table de propriĂ©tĂ©s (
zend_hash_do_resize), l’ancienarDataest libĂ©rĂ© - Une rĂ©fĂ©rence arriĂšre
R:N;ultérieure déréférence alors de la mémoire libérée
đ„ Exploitation locale
L’exploit local (~30 dĂ©clenchements UAF) suit quatre phases :
- Fuite d’adresse heap via un write-through
ZVAL_MAKE_REFdans un spray contrÎlé - Primitive
uaf_read: forge un zvalIS_STRINGpointant vers une adresse arbitraire pour lire la mĂ©moire - Construction d’un faux objet
Closure: localisation dezend_ce_closure,closure_handlers, etzif_system(contournement dedisable_functionsvia la table statiquezend_function_entry[]du module) - Dispatch RCE : appel
$result[33]("id && uname -a")âzif_system
Résultat : exécution en root sous ASLR complet sur PHP 8.5.5 (aarch64).
đ Exploitation distante
L’exploit distant (~2 000 requĂȘtes HTTP POST) cible Docker php:8.5-apache avec Apache mod_php prefork MPM :
- Phase R-1 : fuite heap (1 requĂȘte)
- Phase R-2 : localisation de
libphp.sopar scan ELF (~50â120 requĂȘtes) - Phase R-3 : rĂ©solution de symboles via
.gnu_hash(~10 requĂȘtes) - Phase R-4 : dĂ©couverte de
libc system()via dump du GOT (~1 500â2 000 requĂȘtes) - Phase R-5 : localisation du class entry
stdClass(~55 requĂȘtes) - Phase R-6 : localisation du slot spray (~10 requĂȘtes)
- Phase R-7 : confusion de type â appel
libc system()via vtable forgĂ©e (1 requĂȘte)
PrĂ©condition forte : la cible doit avoir une classe implĂ©mentant Serializable qui appelle unserialize() rĂ©cursivement et agrandit la table de propriĂ©tĂ©s de l’objet interne.
đ Conditions et limites
- L’exploit distant a une prĂ©condition applicative forte (classe gadget spĂ©cifique) limitant sa portĂ©e pratique
- L’exploit local n’a pas cette contrainte
- Testé avec succÚs 3/3 fois sur linux/amd64 et linux/arm64
- La commande shell est limitée à 14 octets utilisables (contrainte GC_ADDREF)
đ Type d’article
Analyse technique approfondie publiĂ©e par Calif, visant Ă documenter une vulnĂ©rabilitĂ© originale dĂ©couverte par IA assistĂ©e d’experts, avec publication du PoC et de l’outil d’audit /php-unserialize-audit.
đ§ TTPs et IOCs dĂ©tectĂ©s
TTP
- T1203 â Exploitation for Client Execution (Execution)
- T1211 â Exploitation for Defense Evasion (Defense Evasion)
- T1059.004 â Command and Scripting Interpreter: Unix Shell (Execution)
IOC
- Chemins :
/dev/shm/x - Chemins :
/dev/tcp
Malware / Outils
- php-unserialize-audit (tool)
- PHPGGC (tool)
đą Indice de vĂ©rification factuelle : 66/100 (haute)
- â blog.calif.io â source reconnue (Rösti community) (20pts)
- â 30748 chars â texte complet (fulltext extrait) (15pts)
- â 2 IOC(s) (6pts)
- ⏠pas d’IOC vĂ©rifiĂ© (0pts)
- â 3 TTPs MITRE identifiĂ©es (15pts)
- â date extraite du HTML source (10pts)
- ⏠aucun acteur de menace nommé (0pts)
- ⏠pas de CVE à vérifier (0pts)
đ Source originale : https://blog.calif.io/p/mad-bugs-finding-and-exploiting-a