
إثبات المفهوم لثغرة XSS مخزنة بعد المصادقة في Autoptimize < 3.1.14، تستغل عدم كفاية تنظيف السمات في إنشاء علامة التحميل المسبق للصور.
الثغرة: XSS مخزنة (مُعتمدة لمستخدمين بمستوى مساهم فما فوق)
الإصدار المتأثر: Autoptimize <= 3.1.13
الإصدار المُصحَّح: Autoptimize 3.1.14
الملف: classes/autoptimizeImages.php
الثغرة موجودة في الطريقة create_img_preload_tag() داخل classes/autoptimizeImages.php. هذه الدالة مسؤولة عن إنشاء وسم <link rel="preload"> للصور الموجودة في المحتوى عند تفعيل تحسين الصور أو ما قبل التحميل.
في الإصدار 3.1.13، تستخدم الدالة نهج "القائمة السوداء" (عبر preg_replace) لإزالة سمات محددة مثل title وalt وclass وid وwidth وheight من وسم `` الأصلي قبل تحويله إلى وسم <link>. ومع ذلك، فهي تفشل في إزالة سمات معالج الأحداث مثل onload أو onerror.
يمكن لمهاجم مُوثّق (بصلاحية مساهم على الأقل) تضمين وسم `` ضار في منشور. عندما يعالج الإضافة هذا المنشور لإنشاء روابط ما قبل التحميل، يتم الاحتفاظ بمعالج الحدث الضار وحقنه في <head> الصفحة داخل وسم <link>. نظرًا لأن <link rel="preload"> يدعم حدث onload، يتم تنفيذ جافا سكريبت عند تحميل المورد.
// 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/HEAD/," 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 تُفعَّل غالبًا للصور التي يتم اكتشافها في نطاق العرض أو التي تم تحميلها مسبقًا بشكل صريح.<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/HEAD/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 وما إلى ذلك، لكن onload يبقى.<link>، ويقوم بتحميل المورد مسبقًا، ويُطلق حدث onload، مما ينفذ الـ XSS.يستبدل التصحيح التعبير النمطي للقائمة السوداء بـ wp_kses()، مما يتيح قائمة بيضاء صارمة للسمات المسموح بها لوسم <link> المُنشأ.
// 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 );