🔍 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’arData de 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’ancien arData est 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 :

  1. Fuite d’adresse heap via un write-through ZVAL_MAKE_REF dans un spray contrĂŽlĂ©
  2. Primitive uaf_read : forge un zval IS_STRING pointant vers une adresse arbitraire pour lire la mémoire
  3. Construction d’un faux objet Closure : localisation de zend_ce_closure, closure_handlers, et zif_system (contournement de disable_functions via la table statique zend_function_entry[] du module)
  4. 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.so par 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