
XSS Armazenado via User-Agent na Visualização de Pedidos do Admin no PhocaCart
PhocaCart ≤ 6.1.7 — Atacante não autenticado armazena payload de XSS via checkout. Executa no contexto do navegador do administrador
O PhocaCart 6.1.7 para Joomla armazena o cabeçalho HTTP User-Agent bruto das solicitações de checkout na tabela de pedidos do banco de dados quando a opção de configuração store_user_agent está habilitada. O valor armazenado é posteriormente renderizado sem codificação HTML na visualização de edição de pedido do administrador via itemText() em Adminview.php.
Um atacante não autenticado pode fazer um pedido com um User-Agent adulterado contendo um payload de JavaScript. Quando um administrador abre o pedido no backend, o payload é executado no contexto do navegador do administrador — permitindo sequestro de sessão, roubo de credenciais ou ações administrativas não autorizadas.
A vulnerabilidade exige que store_user_agent = 1 (não padrão) esteja habilitado. Como essa opção é uma escolha deliberada do administrador para coletar estatísticas de navegador, as lojas afetadas são aquelas em que o proprietário habilitou o recurso — tornando a exploração totalmente silenciosa do ponto de vista do atacante.
| COMPONENTE | VULNERÁVEL | TESTADO EM | CORRIGIDO |
|---|---|---|---|
| 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 armazenado (CWE-79) — direcionado ao administrador
Autenticação necessária: Nenhuma para injetar. Administrador para acionar
Token CSRF necessário: Sim (token CSRF padrão do Joomla obrigatório para o checkout)
Arquivo: administrator/components/com_phocacart/libraries/Phoca/Render/Adminview.php:382
Quando store_user_agent = 1, o método PhocacartUtils::getUserAgent() retorna $_SERVER['HTTP_USER_AGENT'] sem nenhuma sanitização. Essa string bruta é armazenada em #__phocacart_orders (truncada em 200 caracteres — insuficiente para evitar XSS). Quando um administrador visualiza o pedido no backend, itemText() concatena o valor armazenado diretamente na resposta HTML sem nenhuma chamada a htmlspecialchars().
Fluxo de dados:
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 DE ARMAZENAMENTO (ORIGEM VULNERÁVEL)
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 DE RENDERIZAÇÃO (SINK VULNERÁVEL)
// No htmlspecialchars() applied:
$output .= ' <div class="controls ' . $class . '">' . $item . '</div>' . "\n";
Chamado por administrator/components/com_phocacart/views/phocacartorder/tmpl/edit.php:84:
echo $r->itemText($this->itemcommon->user_agent, Text::_('COM_PHOCACART_USER_AGENT'), '', 'user_agent');
A função itemText() passa $item (o valor user_agent armazenado) diretamente para a saída HTML sem nenhuma codificação, tornando-a o principal sink. Corrigir isso no nível do sink protege todos os chamadores de itemText().
A exploração exige concluir um fluxo de checkout completo com um cabeçalho User-Agent malicioso. O token CSRF deve ser obtido primeiro, pois o controlador de checkout do Joomla o valida.
No admin do Joomla, navegue até Componentes → Phoca Cart → Opções → Guia Principal → Opções de Estatísticas. Defina Armazenar Informações do User-Agent = Sim e salve.

O atacante visita o frontend da loja para extrair um token CSRF válido do Joomla, necessário para o controlador de checkout. O token aparece no HTML ou na configuração JavaScript de qualquer página da loja.

O atacante adiciona um produto ao carrinho por meio do endpoint AJAX de checkout usando um User-Agent benigno. Isso faz a sessão de checkout avançar para o próximo estado.

O atacante envia as informações de cobrança para avançar a máquina de estados do checkout.

O atacante seleciona um método de envio para prosseguir para o pagamento.

O atacante seleciona um método de pagamento (ex.: Pagamento na Entrega).

Etapa crítica de injeção. O atacante faz o pedido final via task=checkout.order com o cabeçalho User-Agent definido para o payload de XSS. A tarefa checkout.order lê o HTTP_USER_AGENT bruto e o armazena sem escape em #__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