
CVE-2026-82090 · CVSS 9.2 CRITICAL · Mozilla Pocket의 0-click 저장형 XSS — 모든 버전(v0 → v8.33.0.0) · 18년간 영구 미패치 · 패치 없음 · MITRE 공개
저자: Ing. Zampier Zago (FUNFACTOR1) 부서: Section 1 — Department of Cyber Security, PS 1978 Limited 연락처: [email protected] 웹: www.ps1978ltd.it 분류: 보안 취약점 분석 — CVE-2026-82090
이중 용도 콘텐츠 면책 조항: 이 저장소에는 수명 종료(EOL) 제품에 대한 취약점 분석과 개념 증명(PoC)이 포함되어 있습니다. 제공된 정보와 코드는 오직 교육 목적, 방어적 분석, 그리고 공식 CVE 문서화를 위한 것입니다. 저자는 이 정보의 오용에 대해 어떠한 책임도 지지 않습니다.
https://github.com/user-attachments/assets/e2b0aa46-df64-452b-afbf-fa31dd8c650d
DOM 기반 교차 사이트 스크립팅(XSS) 취약점이 Pocket Android 버전 8.33.0.0(패키지 com.ideashower.readitlater.pro)에서 확인되었으며, 이는 2025년 7월 서비스 종료 전 Mozilla / Read It Later, Inc.가 배포한 마지막 릴리스입니다. 이 취약점을 통해 공격자는 단 한 번의 "Save to Pocket" 동작 외에는 사용자 상호작용 없이 애플리케이션의 WebView에서 임의의 JavaScript를 주입하고 실행할 수 있습니다. 즉, 전달 후 0-click 익스플로잇입니다.
근본 원인은 에셋에 번들된 파일 assets/html/j/articleview-mobile.js(95–99행)에서 jQuery의 .html() 메서드($(document.body).html(content))를 통해 외부에서 가져온 HTML 콘텐츠를 정제 없이 DOM에 직접 주입하는 것입니다. 콘텐츠는 com.pocket.sdk.offline.DownloadingService에 의해 사용자 상호작용 없이 백그라운드에서 자동으로 가져와져 렌더링됩니다.
또한 이 애플리케이션은 addJavascriptInterface를 통해 등록되고 classes2.dex에서 확인된 네이티브 Java-to-JavaScript 브리지(PocketAndroidArticleInterface)를 노출하며, WebView 내에서 실행되는 JavaScript가 이를 호출할 수 있습니다.
벤더 공개 기록: 이 XSS는 2024-07-10에 CWE-79 분류와 전체 기술 세부 정보와 함께 Mozilla Security에 공식 보고되었습니다. Mozilla는 2024-07-11에 접수를 확인하고 Pocket을 범위 밖이라고 선언하며 명시적으로 수정을 거부했습니다. 이후 Mozilla는 2025년에 취약한 코드를 전혀 변경하지 않은 채 v8.33.0.0을 출시했습니다. v8.33.0.0에 대한 포렌식 분석은 articleview-mobile.js의 95–99행에서 동일한 취약한 호출을 확인합니다.
계보: 동일한 이름의 파일 articleview-mobile.js 내 동일한 한 줄 — $(document.body).html(content) — 이 iOS 대응 번들 ReadItLaterPro.app(Pocket iOS v4.5.2)에 존재하며, 이는 Read It Later가 Pocket으로 리브랜딩된 2012년 4월 17일 직전 시대로 거슬러 올라갑니다. 이 CVE는 v0부터 v8.33.0.0까지 모든 버전을 포괄합니다. 즉, 이 결함은 제품의 18년 전체 수명 동안 수정 없이 지속적으로 배포되어 왔습니다(§7 참조). 이용 가능한 가장 오래된 번들(iOS v4.5.2)을 통한 포렌식 코드 수준 확인은 동일한 싱크가 최소 2012년까지 거슬러 올라감을 보여줍니다.
패치는 존재하지 않습니다. 제품은 버려졌습니다. 설치된 모든 인스턴스는 영구적으로 취약한 상태로 남습니다.
| 필드 | 값 |
|---|---|
| CVE | CVE-2026-82090 — 게시일 2026-08-28 — CNA: MITRE Corporation |
| 취약점 유형 | DOM 기반 XSS (0-click) + JavaScript 브리지 악용 |
| CWE | CWE-79, CWE-116 |
| 익스플로잇 상태 | 0-click, 0-day — 패치 없음; 제품 지원 종료(EOL) |
| 벤더 대응 | 2024-07-11 — "Pocket은 범위 밖입니다" (Frida, Mozilla 보안팀) |
| 영향받는 제품 | Pocket Android v8.33.0.0 (최종 릴리스) |
| 패키지 ID | com.ideashower.readitlater.pro |
| 벤더 | Mozilla Corporation / Read It Later, Inc. |
| CVSS v4.0 점수 | 9.2 — CVSS:4.0/AV:N/AC:L/AT:P/PR:N/UI:N/VC:H/VI:H/VA:H/SC:N/SI:N/SA:N |
| 심각도 | CRITICAL |
| 벤더 최초 보고 | 2021-04-19 (페이월 우회) |
| Mozilla 보안팀에 XSS 정식 보고 | 2024-07-10 |
| 취약점이 그대로 남은 최종 APK 릴리스 | 2025 — v8.33.0.0 |
| 서비스 종료 | 2025-07-08 |
| 코드 계보 | 18년 — 모든 버전 (v0 → v8.33.0.0, 2007 → 2025). 2012년 iOS 번들에서 포렌식 코드 확인. |
com.ideashower.readitlater.procom.ideashower.readitlater.pro_8.33.0.0.apkhttps://play.google.com/store/apps/details?id=com.ideashower.readitlater.pro에서 여전히 접근 가능할 수 있으나, 앱은 더 이상 다운로드할 수 없습니다.| 필드 | 값 |
|---|---|
| 유형 | DOM 기반 크로스 사이트 스크립팅 |
| CWE | CWE-79 — 웹 페이지 생성 중 입력의 부적절한 중화 |
| 보조 CWE | CWE-116 — 출력의 부적절한 인코딩 또는 이스케이프 |
| 공격 벡터 | 원격, 0-click (전달 후 사용자 상호작용 없음) |
| 필요한 권한 | 없음 |
| 범위 | 변경됨 — WebView 컨텍스트가 신뢰 경계를 넘어 네이티브 Android 브리지로 침범 |
파일: assets/html/j/articleview-mobile.js
95–99행:
// article content was retrieved
loadCallback : function(content)
{
// TODO : 3.0 : If file was missing, handle that correctly
$(document.body).html(content);
근본 원인: 외부에서 가져온 HTML이 정제 없이 jQuery 3.4.1의 .html() 메서드에 직접 전달됩니다. jQuery 3.4.1은 내장된 <script> 태그와 인라인 이벤트 핸들러(onerror, onload)를 실행합니다. 1,836줄짜리 파일 어디에도 DOMPurify, sanitize(), escapeHtml() 또는 이에 상응하는 호출이 존재하지 않습니다. content 변수는 JS 측 필터링 없이 Java 계층에서 비롯됩니다.
취약한 호출 바로 앞에 있는 // TODO : 3.0 : If file was missing, handle that correctly 주석은 이 코드가 한 번도 프로덕션 수준으로 강화된 적이 없음을 보여줍니다. 이 주석은 최종 릴리스 v8.33.0.0까지 앱의 모든 버전에 존재했습니다.
파일: assets/html/j/articleview-mobile.js, 11–14행:
// Android comm object
if (typeof PocketAndroidArticleInterface == 'undefined')
PocketAndroidArticleInterface = false;
isAndroid = !!PocketAndroidArticleInterface;
DEX 문자열 분석(classes2.dex)을 통해 확인됨:
PocketAndroidArticleInterface
setJavaScriptEnabled
addJavascriptInterface
JS 호출 지점에서 확인된 브리지 메서드: onReady(), onError(), onScrollChanged(), setFrozen(), placePageBlockers(), toggleFullscreen(), setViewType(), scrollToPosition(), onTextSearch(), onRequestedHighlightPatch(), updatePageSwipingDisabledAreas(), getHorizontalMargin(), getMaxMediaHeight(), isConnected().
AndroidManifest.xml에서 확인된 사항:
<service
android:name="com.pocket.sdk.offline.DownloadingService"
android:permission="android.permission.FOREGROUND_SERVICE_DATA_SYNC">
BOOT_COMPLETED 리시버가 등록된 상태입니다. 서비스는 기기 부팅 및 네트워크 사용 가능 시 기사 콘텐츠를 자동으로 가져와 렌더링하며, 사용자 상호작용 없이 숨겨진 WebView에서 loadCallback을 트리거합니다.
Phase 1 — Content Injection [CONFIRMED]
Attacker hosts page with XSS payload.
Victim saves URL via "Save to Pocket".
Malicious HTML stored in local Pocket database.
Phase 2 — Zero-Click Background Sync [CONFIRMED]
DownloadingService auto-starts on boot (BOOT_COMPLETED).
Fetches article content silently, no user interaction.
Phase 3 — Automatic WebView Rendering [CONFIRMED]
Pagination engine (updatePaging) triggers hidden WebView render.
No user opens the article.
Phase 4 — JavaScript Execution [CONFIRMED]
loadCallback calls $(document.body).html(content).
jQuery 3.4.1 executes embedded scripts and event handlers.
Phase 5 — Native Bridge Reachability [PARTIAL]
Bridge object PocketAndroidArticleInterface is reachable from
the XSS execution context (confirmed via classes2.dex string
analysis and JS call-site inventory). Full native method
surface and downstream impact pending complete JADX
decompilation.
<!DOCTYPE html>
<html>
<body>
</body>
</html>
재현 단계:
DownloadingService가 콘텐츠를 자동으로 가져온다.loadCallback → $(document.body).html(content) → 페이로드가 실행된다.