[Write-Up] PortSwigger - Reflected XSS Into a JavaScript String With Angle Brackets and Double Quotes HTML-Encoded and Single Quotes Escaped

목차


문제 분석

난이도: PRACTITIONER
Lab: Reflected XSS into a JavaScript string with angle brackets and double quotes HTML-encoded and single quotes escaped

image.png

검색어는 JavaScript 문자열에 반사된다. 꺾쇠와 큰따옴표는 HTML 인코딩되고 작은따옴표에는 역슬래시가 추가되지만, 역슬래시 자체는 이스케이프되지 않는다. 이 처리 차이를 이용해 문자열을 탈출하고 alert()를 호출하면 문제가 해결된다.

XSS 진단

반사 위치는 다음과 같다.

<script>
    var searchTerms = 'xss';
    document.write('<img src="/resources/images/tracker.gif?searchTerms=' +
                   encodeURIComponent(searchTerms) + '">');
</script>

'를 입력하면 서버가 \'로 바꾸므로 문자열을 닫을 수 없다. 반면 \를 입력해도 추가 이스케이프가 적용되지 않는다. 공격자가 작은따옴표 앞에 역슬래시를 하나 넣으면 서버가 추가한 역슬래시와 \\ 쌍을 이루고, 뒤의 작은따옴표는 더 이상 이스케이프되지 않은 문자열 구분자가 된다.


익스플로잇

다음 검색어를 입력한다.

\';alert(1);//

서버 처리 후 인라인 스크립트는 다음과 같은 형태가 된다.

var searchTerms = '\\';alert(1);//';

\\는 문자열 안의 역슬래시로 소비되고, 작은따옴표가 원래 문자열을 닫는다. 이어지는 alert(1)이 실행되며 //는 뒤에 남은 작은따옴표와 세미콜론을 주석 처리한다.

image.png

페이지를 로드하면 alert()가 호출되어 문제가 해결된다.

image.png


정리

이스케이프를 적용할 때는 이스케이프 문자 자체도 함께 처리해야 한다. 작은따옴표 앞에 역슬래시만 추가하는 방어는 공격자가 선행 역슬래시를 넣어 두 문자를 한 쌍으로 만들면 무력화된다. 가능하면 사용자 데이터를 실행 코드에 문자열 연결하지 않는 구조가 안전하다.