경희대학교 중앙동아리 쿠러그의 정보보안 강의를 기반으로 정리한 글입니다.
XSS game

XSS game은 XSS 공격을 통해 다음과 같이 alert()를 띄우는 게임이다.
Level 1: Hello, world of XSS

해당 창에 "hi"라고 입력하면,

다음과 같이 "hi"가 그대로 뜨는 것을 확인할 수 있다.
주어진 Target code에서 해당 페이지를 보여주는 부분을 찾아보면,
message = "Sorry, no results were found for <b>" + query + "</b>."
해당 코드를 찾을 수 있다.
이 코드를 보면 입력한 대로 query로 들어간다.
때문에, 아래와 같이 입력을 넣어주면 alert()를 띄울 수 있다.
<script>alert()</script>
Level 2: Persistence is key

Level 1을 풀었던 방식으로 입력하면,

원하는 대로 alert()가 뜨지 않고, 위와 같이 날짜 및 시간이 뜬다.
alert()가 뜨지 않는 이는 입력한 구문이 실행되지 않았기 때문이다.
<script></script> 태그 안의 내용은 페이지 로드 시에만 실행된다.
하지만, 댓글만 다는 것으로 페이지가 로드되지 않기에 해당 구문이 실행되지 않는 것이다.
때문에, 아래와 같이 입력을 넣어준 후,


생성된 button을 click해주면 alert()를 띄울 수 있다.
Level 3: That sinking Feeling...

Image 1, 2, 3를 각각 클릭할 때마다 URL의 마지막 숫자가 Image의 숫자에 맞게 변하는 것을 확인할 수 있다.
주어진 Target code에서 해당 페이지를 보여주는 부분을 찾아보면,
html += "<img src='/static/level3/cloud" + num + ".jpg' />";
해당 코드를 찾을 수 있다.
이 코드를 보면 num의 값을 조정해서 공격할 수 있음을 알 수 있다.

num 부분에 '> 이거로 기존 img 태그를 닫아버리고 <script>alert()</script><' 를 넣어주면, (문법 맞춰 오류 방지)
alert()를 띄울 수 있다.
Level 4: Context matters

입력을 넣어보면,

다음과 같이 뜨는 것을 확인할 수 있다.
주어진 Target code에서 해당 페이지를 보여주는 부분을 찾아보면,
<img src="/static/logos/level4.png" />
<br>
<img src="/static/loading.gif" onload="startTimer('{{ timer }}');" />
<br>
<div id="message">Your timer will execute in {{ timer }} seconds.</div>
해당 코드를 찾을 수 있다.
이 코드를 보면 입력한 대로 {{ timer }} 로 들어간다.

{{ timer }} 부분에 '); 이거로 기존 onload 함수를 닫아버리고 alert(); (' 를 넣어주면, (문법 맞춰 오류 방지)
alert()를 띄울 수 있다.
Level 5: Breaking protocol

위 페이지는 초기 페이지에서 'Sign up'을 눌렀을 때 나오는 페이지이다.
주어진 Target code에서 해당 페이지를 보여주는 signup.html 코드를 찾아보면,
<a href="{{ next }}">Next >></a>
해당 코드를 찾을 수 있다.
이 코드를 보면 next의 값이 html 코드의 {{ next }} 부분에 그대로 삽입되는 것을 확인할 수 있다.

뒤에 나오는 javascript 구문을 실행하게 하는 javascript:를 이용해 위와 같이 URL을 수정하고,
'Next >>'를 누르면 alert()를 띄울 수 있다.
Level 6: Follow the rabit

위 페이지에 해당하는 코드를 확인하면,
// Show log messages
scriptEl.onload = function() {
setInnerText(document.getElementById("log"),
"Loaded gadget from " + url);
}
scriptEl.onerror = function() {
setInnerText(document.getElementById("log"),
"Couldn't load gadget from " + url);
}
해당 코드를 찾을 수 있다.
이 코드를 보면 URL의 #뒤에 적힌 url 경로를 통해 로드하는 것을 확인할 수 있다.

마지막 힌트를 이용해,

다음과 같이 url을 로드할 하였는데 실패했다.
로드를 실패하는 이유를 찾아보면,
// This will totally prevent us from loading evil URLs!
if (url.match(/^https?:\/\//)) {
setInnerText(document.getElementById("log"),
"Sorry, cannot load a URL containing \"http\".");
return;
}
해당 코드를 찾을 수 있다.
이 코드를 보면 URL이 https로 되어있으면 안 된다는 것을 알 수 있다. (프로토콜 생략 시 현재 문서와 같은 프로토콜로 자동 지정)

때문에 https를 Https로 바꿔주면, (프로토콜은 대소문자 구분 안 함)

gadget가 로드된 것을 확인할 수 있다.

이때 callback하는 함수만 foo에서 alert로 바꿔주면 alert()를 띄울 수 있다.
'Security > 정보보안' 카테고리의 다른 글
정보보안 3차시: 웹 - SQL Injection (3) | 2025.03.31 |
---|---|
정보보안 2차시: 웹 - 기본적인 웹 취약점 (2) | 2025.03.28 |
정보보안 1차시: 네트워크 - ARP와 TCP/UDP (5) | 2025.03.21 |