
XSS persistente tramite User-Agent nella visualizzazione degli ordini admin in PhocaCart
PhocaCart ≤ 6.1.7 — Un attaccante non autenticato memorizza un payload XSS tramite il checkout. Si esegue nel contesto del browser dell'amministratore
PhocaCart 6.1.7 per Joomla memorizza l'header HTTP User-Agent grezzo proveniente dalle richieste di checkout nella tabella degli ordini del database quando l'opzione di configurazione store_user_agent è abilitata. Il valore memorizzato viene successivamente renderizzato senza codifica HTML nella vista di modifica dell'ordine dell'amministratore tramite itemText() in Adminview.php.
Un attaccante non autenticato può effettuare un ordine con uno User-Agent appositamente creato contenente un payload JavaScript. Quando un amministratore apre l'ordine nel backend, il payload viene eseguito nel contesto del browser dell'amministratore — consentendo il dirottamento della sessione, il furto di credenziali o azioni amministrative non autorizzate.
La vulnerabilità richiede l'abilitazione di store_user_agent = 1 (non predefinito). Poiché questa opzione è una scelta deliberata dell'amministratore per raccogliere statistiche sui browser, i negozi interessati sono quelli in cui il proprietario del negozio ha abilitato la funzionalità — rendendo lo sfruttamento completamente silenzioso dal punto di vista dell'attaccante.
| COMPONENTE | VULNERABILE | TESTATO SU | CORRETTO |
|---|---|---|---|
| PhocaCart (com_phocacart) | 5.0.0 – 6.1.7 | Joomla 5.4.7 + PhocaCart 6.1.7 + MariaDB 10.6 | 6.1.8 |
Tipo: XSS memorizzato (CWE-79) — mirato all'amministratore
Autenticazione richiesta: Nessuna per l'iniezione. Amministratore per l'attivazione
Token CSRF richiesto: Sì (token CSRF standard di Joomla richiesto per il checkout)
File: administrator/components/com_phocacart/libraries/Phoca/Render/Adminview.php:382
Quando store_user_agent = 1, il metodo PhocacartUtils::getUserAgent() restituisce $_SERVER['HTTP_USER_AGENT'] senza alcuna sanificazione. Questa stringa grezza viene memorizzata in #__phocacart_orders (troncata a 200 caratteri — non sufficiente per prevenire l'XSS). Quando un amministratore visualizza l'ordine nel backend, itemText() concatena il valore memorizzato direttamente nella risposta HTML senza alcuna chiamata a htmlspecialchars().
Flusso dei dati:
Attacker sends checkout request:
User-Agent: <script>alert(document.domain)</script>
utils.php:334 PhocacartUtils::getUserAgent()
└─ return (string) $_SERVER['HTTP_USER_AGENT'] // raw, no sanitization
order.php:413 $d['user_agent'] = substr($user_agent, 0, 200)
└─ INSERT INTO #__phocacart_orders (user_agent) VALUES ('<script>...</script>')
Admin opens order in backend:
edit.php:84 echo $r->itemText($this->itemcommon->user_agent, ...)
Adminview.php:382 '<div class="controls >' . $item . '</div>'
// → NO htmlspecialchars()
→ Browser renders: <div><script>alert(document.domain)</script></div>
→ XSS fires in administrator's browser
ORDER.PHP — FASE DI MEMORIZZAZIONE (SORGENTE VULNERABILE)
administrator/components/com_phocacart/libraries/phocacart/order/order.php:424
$user_agent = PhocacartUtils::getUserAgent(); // reads $_SERVER['HTTP_USER_AGENT'] raw
$d['user_agent'] = substr($user_agent, 0, 200); // stored in DB unfiltered
ADMINVIEW.PHP:382 — FASE DI RENDERING (SINK VULNERABILE)
// No htmlspecialchars() applied:
$output .= ' <div class="controls ' . $class . '">' . $item . '</div>' . "\n";
Chiamata da administrator/components/com_phocacart/views/phocacartorder/tmpl/edit.php:84:
echo $r->itemText($this->itemcommon->user_agent, Text::_('COM_PHOCACART_USER_AGENT'), '', 'user_agent');
La funzione itemText() passa $item (il valore user_agent memorizzato) direttamente nell'output HTML senza codifica, rendendola il sink principale. Correggerla a livello di sink protegge tutti i chiamanti di itemText().
L'attacco richiede il completamento dell'intero flusso di checkout con un header User-Agent malevolo. Il token CSRF deve essere ottenuto per primo poiché il controller di checkout di Joomla lo valida.
Nell'amministrazione di Joomla, vai su Components → Phoca Cart → Options → scheda Main → Statistics Options. Imposta Store User Agent Information = Yes e salva.

L'attaccante visita il frontend del negozio per estrarre un token CSRF valido di Joomla richiesto dal controller di checkout. Il token appare nel sorgente HTML o nella configurazione JavaScript di qualsiasi pagina del negozio.

L'attaccante aggiunge un prodotto al carrello tramite l'endpoint AJAX di checkout usando uno User-Agent benigno. Questo fa avanzare la sessione di checkout allo stato successivo.

L'attaccante invia le informazioni di fatturazione per far avanzare la macchina a stati del checkout.

L'attaccante seleziona un metodo di spedizione per procedere al pagamento.

L'attaccante seleziona un metodo di pagamento (ad es., contrassegno).
