
Prova de conceito para XSS armazenado autenticado no Autoptimize < 3.1.14, explorando a sanitização insuficiente de atributos na geração de tags de pré-carregamento de imagens.
Vulnerabilidade: Cross-Site Scripting (XSS) Armazenado Autenticado (Colaborador+)
Versão Afetada: Autoptimize <= 3.1.13
Versão Corrigida: Autoptimize 3.1.14
Arquivo: classes/autoptimizeImages.php
A vulnerabilidade existe no método create_img_preload_tag() dentro de classes/autoptimizeImages.php. Essa função é responsável por gerar tags <link rel="preload"> para imagens encontradas no conteúdo quando a otimização de imagens ou o pré-carregamento está habilitado.
Na versão 3.1.13, a função utiliza uma abordagem de "lista negra" (via preg_replace) para remover atributos específicos como title, alt, , , e da tag `` original antes de convertê-la em uma tag . No entanto, ela não remove atributos de manipuladores de eventos, como ou .
classidwidthheight<link>onloadonerrorUm atacante autenticado (com pelo menos a função de Colaborador) pode incorporar uma tag `` maliciosa em um post. Quando o plugin processa esse post para gerar links de pré-carregamento, o manipulador de eventos malicioso é preservado e injetado no <head> da página dentro de uma tag <link>. Como <link rel="preload"> suporta o evento onload, o JavaScript é executado quando o recurso é carregado.
// classes/autoptimizeImages.php
public static function create_img_preload_tag( $tag ) {
// ...
// rewrite img tag to link preload img.
$_from = array( '<img ', ' src="https://raw.githubusercontent.com/ciscocamelo/cve-2025-13401-xss-stored/main/," sizes=', ' srcset=' );
$_to = array( '<link rel="preload" as="image" ', ' href=', ' imagesizes=', ' imagesrcset=' );
$tag = str_replace( $_from, $_to, $tag );
// INSUFFICIENT SANITIZATION: Only removes specific attributes
$tag = preg_replace( '/ ((?:title|alt|class|id|loading|fetchpriority|decoding|data-no-lazy|width|height)=".*")/Um', '', $tag );
// ...
return $tag;
}
create_img_preload_tag é frequentemente acionada para imagens detectadas no viewport ou explicitamente pré-carregadas.<img src="https://example.com/image.jpg" onload="alert('XSS_POC_SUCCESS')">
<!-- Malicious Image -->
<img src="https://raw.githubusercontent.com/ciscocamelo/cve-2025-13401-xss-stored/main/wp-content/plugins/autoptimize/classes/external/js/lazysizes.min.js" onload="alert(document.cookie)">
<link rel="preload" as="image" href="/wp-content/plugins/autoptimize/classes/external/js/lazysizes.min.js" onload="alert(document.cookie)">
width, height, etc. podem ser removidos, mas onload permanece.<link>, pré-carrega o recurso e dispara o evento onload, executando o XSS.A correção substitui a regex de lista negra por wp_kses(), habilitando uma lista branca estrita de atributos permitidos para a tag <link> gerada.
// classes/autoptimizeImages.php v3.1.14
$allowed_html = array(
'link' => array(
'rel' => true,
'as' => true,
'href' => true,
'imagesizes' => true,
'imagesrcset' => true,
'type' => true,
'media' => true,
),
);
$tag = wp_kses( $tag, $allowed_html );