Lobsters

Scalable Vector Grief

확장 가능한 벡터 골칫거리

PortSwigger 연구자가 SVG 위생 처리 라이브러리 8종을 시험해 6종의 우회 방법을 공개했습니다. 네임스페이스 혼동, XSLT와 Firefox 응답 헤더, Safari의 GIF 처리로 스크립트를 실행할 수 있었으며 DOMPurify 등 두 라이브러리는 우회되지 않았습니다.

에디터 노트

이번 사례에서 가장 설득력 있는 대목은 SVG 위생 처리기가 태그 목록만 검사해서는 충분하지 않다는 점입니다. XML 네임스페이스와 브라우저의 요소 처리 차이, 응답 헤더의 Link 처리, Safari의 이미지 가져오기처럼 문서 바깥의 동작도 공격 경로가 됩니다. 특히 본문이 무해한 XML이어도 Firefox가 헤더의 XSLT 스타일시트를 처리한다는 설명은 본문만 검사하는 방어의 한계를 구체적으로 보여줍니다. 연구 결과는 여덟 라이브러리 가운데 여섯 곳에서 찾은 우회 사례이며, DOMPurify와 darylldoyle/svg-sanitizer는 제시된 공격을 막았습니다. 따라서 이 결과만으로 모든 SVG 위생 처리기가 취약하다고 일반화할 수는 없습니다. 댓글의 SVG 기능 축소 제안은 XML 자체의 공격 경로와 브라우저별 동작까지 없애지 못한다는 답글과 부딪힙니다. 형식의 기능을 제한하는 것과 각 구현에서 실제로 어떤 문서를 어떻게 처리하는지 검증하는 일은 별개의 과제로 남습니다.

AI 요약

PortSwigger 연구자는 인기 SVG 위생 처리 라이브러리 8종을 시험해 6종에서 우회 방법을 찾았습니다. SVG는 스크립트와 이벤트 핸들러, 링크, 애니메이션, 내장 HTML을 담을 수 있어 업로드 전에 위생 처리를 거치는 경우가 많습니다. 공개된 사례는 브라우저별 XML 처리와 라이브러리의 파싱 방식 차이가 방어를 무력화하는 과정을 보여줍니다.

라이브러리별 우회

mattkrick/sanitize-svg에서는 XHTML 네임스페이스를 지정한 frame이나 iframe을 SVG 안에 넣어 JavaScript URL 또는 srcdoc 스크립트를 실행했습니다. foreignObject는 브라우저가 이름을 foreignObject로 바꾼 뒤 라이브러리가 소문자 foreignobject로 요소를 검색해 놓친다고 설명합니다. 중첩 SVG의 onload 핸들러도 통과했습니다.

Borewit/svg-sanitizer는 animate 요소를 그대로 허용해 링크의 href를 JavaScript URL로 바꾸는 방식으로 우회했습니다. animateTransform을 이용해 Safari에서 링크 주소를 바꾸는 기법도 제시했습니다.

bgalek/safe-svg, mattkrick/sanitize-svg, alnorris/SVG-Sanitizer에서는 XSLT 스타일시트를 data URL로 지정하는 방법이 통했습니다. XSLT가 SVG에 HTML 스크립트를 만들 수 있으며, 해당 기능은 폐기 예정으로 2026년 11월 제거될 예정이라고 글은 설명합니다. 연구자는 Firefox의 Link 응답 헤더로 외부 CSS를 불러오는 동작에서 착안해 XSLT도 헤더에 넣었습니다. 응답 본문은 무해한 XML이어도 헤더가 data URL 스타일시트를 지정하면 Firefox에서 문서 출처로 JavaScript가 실행됩니다. 이 방식은 cloudflare/svg-hush, jams2/py-svg-hush, bgalek/safe-svg에 영향을 줬습니다.

Safari의 이미지 처리

Safari는 SVG의 use 요소로 참조한 이미지 파일을 SVG처럼 가져올 수 있습니다. 연구자는 SVG 내용을 담은 GIF를 직접 열면 렌더링되지 않지만, 같은 출처의 SVG에서 use로 참조하면 GIF 안의 요소와 이벤트 핸들러가 처리되는 방법을 제시했습니다. 이 기법은 앞서 언급한 세 라이브러리를 우회합니다.

결과와 범위

연구자는 아직 이름을 공개할 수 없는 애플리케이션 두 곳에서도 악용했다고 밝혔습니다. DOMPurify와 darylldoyle/svg-sanitizer는 제시한 모든 공격을 막았습니다.

Lobsters 반응

  • @serce — 인라인 스크립트와 foreignObject 등 XSS 및 유사한 문제를 일으키는 요소를 전부 금지하는 SVG v2를 만들려면 무엇이 필요할지 궁금합니다.
    • @masklinn — SVG Tiny 1.1이 그랬지만 1.2에서 스크립트 기능을 다시 추가했습니다. XML 자체에 있는 공격 경로도 제거하지 못합니다.
    • @singpolyma — UTF-8 등에 들어 있는 공격 경로도 마찬가지입니다. 모든 것이 어느 지점에서는 취약합니다.

원문: PortSwigger / 번역·요약: Trawling