1. 문제
1) 문제 확인
위에 Image 1,2,3 탭을 선택하면 탭마다 설정된 사진이 나온다. 탭을 누를때마다 파라미터의 인자가 해당 숫자에 맞는 이미지로 설정되어 나온다.
2. 접근방법
그렇다면 저 탭을 눌렀을때 어떻에 동작하는지를 우선 파악해야 한다.
<!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" />
<!-- Load jQuery -->
<script
src="//ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js">
</script>
<script>
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);
window.location.hash = num;
// Select the current tab
var tabs = document.querySelectorAll('.tab');
for (var i = 0; i < tabs.length; i++) {
if (tabs[i].id == "tab" + parseInt(num)) {
tabs[i].className = "tab active";
} else {
tabs[i].className = "tab";
}
}
// Tell parent we've changed the tab
top.postMessage(self.location.toString(), "*");
}
window.onload = function() {
chooseTab(unescape(self.location.hash.substr(1)) || "1");
}
// Extra code so that we can communicate with the parent page
window.addEventListener("message", function(event){
if (event.source == parent) {
chooseTab(unescape(self.location.hash.substr(1)));
}
}, false);
</script>
</head>
<body id="level3">
<div id="header">
<img id="logo" src="/static/logos/level3.png">
<span>Take a tour of our cloud data center.</a>
</div>
<div class="tab" id="tab1" onclick="chooseTab('1')">Image 1</div>
<div class="tab" id="tab2" onclick="chooseTab('2')">Image 2</div>
<div class="tab" id="tab3" onclick="chooseTab('3')">Image 3</div>
<div id="tabContent"> </div>
</body>
</html>
JavaScript
복사
이미지 버튼을 클릭했을때, onClick 이벤트로 chooseTab() 핸들러가 등록되어있다. 1번 버튼을 누르면 chooseTab('1')이 호출된다. chooseTab() 함수를 다시 보면
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);
window.location.hash = num;
// Select the current tab
var tabs = document.querySelectorAll('.tab');
for (var i = 0; i < tabs.length; i++) {
if (tabs[i].id == "tab" + parseInt(num)) {
tabs[i].className = "tab active";
} else {
tabs[i].className = "tab";
}
}
// Tell parent we've changed the tab
top.postMessage(self.location.toString(), "*");
}
JavaScript
복사
요렇게 되어있다. 인자로 들어온 num을 parseInt로 형변환을하여 html 변수에 "Image" + 에 이어 붙인다. 그다음 다시 num을 <img> 태그의 src에 경로중 파일명으로 하여 이어붙인다. 여기서 아무 필터링이 없기 때문에, 조작이 가능하다.
어쨋든 정상적으로는 1,2,3 중 하나의 값이 들어오므로 만약 1이 들어온 경우 html에는
html = " Image1 <br> <img src='/static/level3/cloud1.jpg'> "
요렇게 문자열이 저장될 것이다. 그다음 tabContent이라는 id 값을 가지는 Dom에 위 html 문자열을 .html()를 이용하여 삽입한다. 그러면 동적으로 저 문자열이 브라우저에 출력된다.
그다음 현재 선택된 tab의 class 명을 tab active로 변경한다. 그리고 마지막으로 top.post... 함수를 어떠한 origin에도 상관없이 메시지를 보낸다. 이는 부모에게 현재 tab이 수정되었기 때문에 알려주는 기능이라고 주석에 써져있다.
해당 postMessage가 전송되면, addEventListener() 함수에서 이를 수신하는 역할을 한다.
window.onload = function() {
chooseTab(unescape(self.location.hash.substr(1)) || "1");
}
// Extra code so that we can communicate with the parent page
window.addEventListener("message", function(event){
if (event.source == parent) {
chooseTab(unescape(self.location.hash.substr(1)));
}
}, false);
JavaScript
복사
저 부분이 이해가 잘 안가서 구글링하면서 찾아본 결과 iframe과 같이 부모 자식 페이지간에 원래는 origin의 규칙이 서로 다른 경우는 통신이 안되지만 저렇게 postMessage로 송신하고 addEvent로 수신하는 로직을 이용하면 가능하다고 한다.
해당 페이지가 iframe로 된거같지는 않지만..? 뭐 어쨋든 주석에도 부모 페이지와 통신을 하기 위한 로직이라고 써져 있다. postMessage가 송신되면, 부모페이지로부터 전달받은 message 이벤트가 발생했을때, 두번째 인자인 함수핸들러가 호출된다.
저 함수안에는 현재 이벤트가 부모에서 발생한 것이라면, url 파라미터를 unescape하여 chooseTab을 호출한다. window.onload함수는 모든 리소스들이 로딩이 되면 호출되는 함수로서 이 안에서 한번더 chooseTab을 호출한다.
아마도 현재 페이지는 url.../frame# {1,2,3} 요부분이 달리지므로 저기 상위 url이 부모, 변경되는 1,2,3 페이지들이 자식 페이지인것같다. 그리고 부모 자식, 페이지의 소스코드가 동일한것같다.
요건 내가 잘못 판단함.
저기 url을 따로 새창에서 열어서 봤었는데 왜자꾸
요 부분이 지혼자 계속 로딩되지;; 했는데 , 저 주석에 써져있는 부모 페이지와 통신하는게
요렇게 둘이 통신하는듯..?
뭐 어쨋든 소스코드는 분석이 됬으니 저기 이미지 위에 나오는 Image 2 ⇒ 요부분이 url #다음 파라미터로 들어가고 아무 필터링이 없는걸 확인했으니, img 태그를 종료하고 스크립트 태그를 넣으면 될것이다.
•
payload
'><img src='1' onerror='alert(1)'>
3. 풀이
4. 몰랐던 개념
•
window.onload ⇒ 모든 리소스가 다 로딩되고 브라우저에서 호출됨
•
addEventListener ⇒ onload보다 호출시점이 빠름. 첫번째 인자로 세팅된 이벤트가 발생했을때, 2번째 인자로 설정한 핸들러가 호출됨.