XSS
개념
- 사용자가 악성 스크립트를 실행하게 한다.
- 공격자가 사용자로 가장하고 사용자가 수행할 수 있는 모든 작업을 수행할 수 있다.
- XSS를 방어하기 위해 설치된 필터링을 우회한다.
- 동일 출처 정책을 우회한다.
종류
Context에 따른 분류
반사되는 데이터에 따라 분류할 수 있다.
HTML tags 사이에 XSS
XSS 컨텍스트가 HTML 태그 사이의 텍스트인 경우 javascript 실행을 트리거하도록 설계된 새로운 HTML 태그를 도입해야 한다.
<script>alert(document.domain)</script>
<img src=1 onerror=alert(1)>위와 같이 script 태그에 페이로드를 넣거나, 다른 태그의 핸들러에 페이로드를 넣는다.
참고 문제: Portswigger-Reflected XSS into HTML context with nothing encoded
HTML 태그 속성에 XSS
HTML 태그 속성 값에 입력값이 들어가는 경우, 속성 값 입력에서 탈출하고 새로운 태그를 만들어 XSS 한다. 예를 들어 "><script>alert(document.domain)</script> 와 같이 "로 속성값 입력을 종료하고, >로 이전 태그를 닫은 후 새로운 태그를 만들어 자바스크립트를 실행한다.
더 일반적인 상황에서는 > 문자가 차단되거나 인코딩된다. 속성값 입력만 종료할 수 있는 경우 이벤트 핸들러를 끼워넣어 XSS 한다. 예를 들어 " autofocus onfocus=alert(document.domain) x=" 와 같이 핸들러를 끼워넣는다. 마지막에 x=" 로 뒤쪽의 " 를 처리한다.
참고 문제: Portswigger-Reflected XSS into attribute with angle brackets HTML-encoded
때때로 XSS 컨텍스트는 자체적으로 스크립팅 가능한 컨텍스트를 생성할 수 있는 HTML 태그 속성에 속하기도 한다. 예를 들어 href와 같은 속성에 들어가는 경우가 있다. href 속성 값으로 javascript:alert(1) 등을 설정하면 곧바로 XSS가 가능하다.
href에 javascript 스키마 URL을 넣을 때는 HTML 인코딩이나 URL 인코딩도 가능하다. 예를 들어 href="javascript:alert%281%29"나 href="javascript:alert(1)"도 가능하다. (정확히는 태그 속성 값이 HTML 인코딩이 가능하다.)
참고 문제: // Todo
일반적으로 이벤트를 자동으로 실행하지 않는 태그인 canonical link 태그에서도 XSS를 할 수 있는 방법이 있다. accessKey 속성을 사용하면 특정 요소를 참조하는 바로가기 키를 제공할 수 있다. 윈도우에서 alt+shift+지정키, 맥에서 ctrl+alt+지정키, 리눅스에서 alt+지정키를 누르면 트리거된다. 이를 이용하면 canonical link 태그에도 XSS가 가능하다.
참고 문제: Portswigger-Reflected XSS in canonical link tag
Javascript에 XSS
기존 코드 종료시키기
XSS 컨텍스트가 기존 javascript에 있을 때는 다양한 상황이 발생할 수 있다. 기존 스크립트를 종료한 후 새로운 HTML 태그를 도입해 XSS를 트리거할 수 있다.
<script>
...
var input = 'controllable data here';
...
</script> input 변수에 사용자의 입력이 반사되어 javascript 코드가 동적으로 생성되는 경우, 임의로 </script> 태그를 넣어 기존 script 태그를 닫고 새로운 태그를 열어 XSS를 할 수 있다. </script><img src=1 onerror=alert(document.domain)> 와 같은 페이로드를 넣어 기존 javascript의 아랫부분을 날린 후 원하는 작업을 끼워넣는 식이다.
이것이 작동하는 이유는 브라우저가 먼저 HTML 구문 분석을 수행하여 스크립트 블록을 포함한 페이지 요소를 식별하고, 이 작업이 끝난 후에 javascript 구문 분석을 수행, 실행하기 때문이다.
참고 문제: Portswigger-Reflected XSS into a JavaScript string with single quote and backslash escaped
Javascript string 부수기
XSS 컨텍스트가 javascript 코드의 문자열 데이터로 하드코딩되는 경우가 있다. 구문 오류가 있으면 전체 스크립트가 실행되지 않기 때문에 뒤쪽 코드를 잘 처리하는 것도 중요하다. '-alert(document.domain)-' 와 같이 연산자로 연결하거나 ';alert(document.domain)//와 같이 문자열 종료 후 코드를 끼워넣고 뒤쪽 코드는 주석처리하는 방법이 있다.
참고 문제: Portswigger-Reflected XSS into a JavaScript string with angle brackets HTML encoded
일부 프로그램은 ' 문자에 백슬래시를 붙여 이스케이프하려 한다. 이 상황에서 프로그램이 백슬래시 문자 자체를 이스케이프하지 못하는 실수를 한다. 공격자가 백슬래시 문자를 직접 추가하면 프로그램이 추가한 백슬래시를 무효화할 수 있다.
';alert(document.domain)// 가 \';alert(document.domain)// 로 이스케이프 되는 경우, \';alert(document.domain)// 를 입력하면 \\';alert(document.domain)// 가 되어 우회할 수 있다.
일부 웹사이트는 사용이 허용된 문자를 제한하여 XSS를 더 어렵게 한다. 웹사이트 수준에서 또는 요청이 아예 웹사이트에 도달하지 못하도록 WAF를 이용한다. 이런 상황에서는 이러한 보안 조치를 우회하는 함수를 호출하는 다른 방법을 실험해야 한다. 이를 수행하는 한 가지 방법은 예외 핸들러와 함께 throw 문을 사용하는 것이다. 이를 통해 괄호를 사용하지 않고 함수에 인수를 전달할 수 있다.
예를 들어 onerror=alert;throw 1는 () 문자를 사용하지 않고 alert 함수에 1을 파라미터로 넣는다. alert 함수를 전역 예외 핸들러에 할당하고, throw 문에서 1을 예외 핸들러(alert)에 전달한다.
참고 문제: Portswigger-Reflected XSS in a JavaScript URL with some characters blocked
HTML 인코딩을 사용하기
XSS 컨텍스트가 태그 속성 내의 기존 javascript인 경우 HTML 인코딩을 사용해 일부 필터를 우회할 수 있다. 브라우저가 응답에서 HTML 태그 및 속성 구문분석을 할 때, 더 처리되기 전에 속성 값의 HTML 디코딩을 수행한다.
예를 들어 <a href="#" onclick="... var input='controllable data here'; ..."> 와 같은 경우 입력값으로 '-alert(document.domain)-' 를 넣으면 ’ 문자에 대한 차단 또는 이스케이프를 우회할 수 있다. javascript가 해석되기 전에 '가 ’ 문자로 디코딩된다.
참고 문제: // Todo
Javascript 템플릿 리터럴에 XSS
Javascript 템플릿 리터럴은 임베디드 Javascript 표현식을 허용하는 문자열이다. 일반적으로 텍스트를 연결할 때 사용된다. 템플릿 리터럴은 일반 따옴표 대신 백틱(`) 문자로 묶이며, 임베디드 표현식은 ${...} 형식으로 쓴다.
예를 들어 다음과 같은 모습이다.
document.getElementById('message').innerText = `Welcome, ${user.displayName}.`; XSS 컨텍스트가 javascript 템플릿 리터럴에 있으면 리터럴을 종료할 필요가 없다. 대신 ${...} 구문을 사용하여 리터럴이 처리될 때 실행될 javascript를 삽입하면 된다.
예를 들어 다음과 같은 코드가 있다. input은 백틱으로 묶인 템플릿 리터럴로, 유저의 입력이 들어간다.
<script>
...
var input = `controllable data here`;
...
</script> 이 때, 입력값으로 ${alert(document.domain)}를 넣으면 템플릿 리터럴을 직접 닫지 않고도 스크립트를 실행할 수 있다.
라이브러리별 취약점
AngularJS sandbox
// Todo
XSS 난독화
- 입력 검증 스크립트의 문제점은 XSS 공격을 인코딩하는 방법이 아주 다양하여 필터링이 실패한다는 것이다. 문제는 어떤 인코딩이 우회에 성공하는지 판별하는 것이다. (해커 플레이북 pg. 86)
크라우드 소싱
- reddit XSS에서 검색하면 손쉽게 XSS 취약점을 찾을 수 있다. 서브레딧에서 다른 사람들이 발견한 XSS 예제들을 볼 수 있다. (해커 플레이북 pg. 86)
OWASP 치트 시트
- 또 다른 주요 정보 출처로 OWASP의 우회 치트 시트가 있다. xss-filter-evasion-cheatsheet (해커 플레이북 pg. 87)
참고
- portswigger academy
- portswigger academy - context에 따라 분류
- portswigger academy - cheatsheet
- portswigger academy - angularjs XSS
tags: web hacking