
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).

Passaggio di iniezione critico. L'attaccante effettua l'ordine finale tramite task=checkout.order con l'header User-Agent impostato al payload XSS. Il task checkout.order legge l'HTTP_USER_AGENT grezzo e lo memorizza senza escaping in #__phocacart_orders.user_agent.
POST /index.php/shop/checkout HTTP/1.1
Host: TARGET
User-Agent: <script>alert(document.domain)</script>
Content-Type: application/x-www-form-urlencoded
phcheckouttac=1&task=checkout.order&option=com_phocacart&return=&<CSRF_TOKEN>=1
Risultato: ordine creato. Il database memorizza user_agent = '<script>alert(document.domain)</script>'.

L'amministratore va su Components → Phoca Cart → Orders. L'ordine iniettato appare nell'elenco. L'XSS non è ancora attivato in questa fase.

Quando l'amministratore fa clic sull'ordine per aprire la vista di modifica, lo user_agent memorizzato viene renderizzato senza escaping tramite itemText(). JavaScript viene eseguito immediatamente.
URL di attivazione:
/administrator/index.php?option=com_phocacart&view=phocacartorder&layout=edit&id=<ORDER_ID>
