-
XSS-Game#02. 기존공부/#02.3 웹해킹 2019. 4. 12. 18:18
1. 머릿말
XSS-gmae.appspot.com 문제를 풀어본다.2. 풀이
(1) level 1
[level 1 화면] 답: <script>alert(1);</script>
(2) level 2
[level 2 화면] 답: <img src/ onerror=alert(1);>
(3) level 3
[level 3 화면] 풀이: [Image 1], [Image 2], [Image 3] 탭을 클릭할 시 chooseTb('1'), chooseTab('2'), chooseTab('3')을 호출한다.
1234567891011121314151617181920212223242526272829303132333435function chooseTab(num) {// 적절한 이미지를 동적으로 로드var html = "Image " + parseInt(num) + "<br>";// HERE ATTACK VECTORhtml += "<img src='/static/level3/cloud" + num + ".jpg' />";$('#tabContent').html(html);window.location.hash = num;// 현재 탭 선택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";}}// Parent에게 탭을 변경했다고 알림top.postMessage(self.location.toString(), "*");}window.onload = function() {chooseTab(unescape(self.location.hash.substr(1)) || "1");}// Parent 페이지와 통신할 수 있도록 하는 xtra 코드window.addEventListener("message", function(event){if (event.source == parent) {chooseTab(unescape(self.location.hash.substr(1)));}}, false);cs <IMG 태그를 변경이 가능할 듯 하다. <IMG SRC='/static/level3/cloud[#뒤의 number].jpg>와 같은 형식으로 전송된다.
답: >%0A<img src/ onerror=alert(1);>
(4) level 4
[level 4 화면] 타이머인척 하는 홈페이지가 존재한다. 3을 입력하면 3초 뒤에 Time is up! 이라는 알림창이 출력된다. 아래는 Network에서 전송되는 데이터 중 Time is up!이라는 알림문구를 띄워주는 Javascript 부분을 추출한 것이다.
1234567function startTimer(seconds) {seconds = parseInt(seconds) || 3;setTimeout(function() {window.confirm("Time is up!");window.history.back();}, seconds * 1000);}cs seconds에 3이나 입력한 값이 들어간다. 여기서 parseInt함수는 문자열을 정수로 바꾸는 함수이다. parseInt( String, n)과 같은 형식으로 사용하며 n(사용할 진수/ 2진수, 10진수 등)을 입력하지 않으면 10진수로 해석한다.
사실 여기는 별 상관이 없다.
1s HTML 코드의 이부분에 입력한 값이 그대로 출력된다. 1');alert;('1를 입력하면 문제를 클리어 할 수 있을 것이다. 그러나 세미콜론(;) 뒤 문자의 경우 GET 방식에서 누락되는 상황이 발생한다.
테스트로 ;1를 입력하니 홈페이지가 반응하지 않았다.
;을 url 인코딩 해주자.
풀이: 1')%3Balert('1
(5) level 5
[level 5 화면] 매우 심플한 화면이다.
소스코드를 살펴보면 Sign up 페이지를 누를 시 아래의 주소로 이동한다.
https://xss-game.appspot.com/level5/frame/signup?next=confirm
체크한 confirm 파라미터의 value를 직접 HTML 코드로 반영하고 있다.
URL 부분이며 HREF 부분의 값은 브라우저의 주소창에 그대로 반영된다. URL Scheme이다. view-source:와 같이 javascript: 형식을 사용한다면 alert를 출력할 수 있다.
풀이: javascript:alert(1);
(6) level 6
[level 6 화면] 더욱 심플해졌다. 소스코드를 살펴보니 아래와 같은 javascript를 발견할 수 있었다.
12345678910111213141516171819202122232425262728293031323334353637383940414243444546function setInnerText(element, value) {if (element.innerText) {element.innerText = value;} else {element.textContent = value;}}function includeGadget(url) {var scriptEl = document.createElement('script');// 악의적인 URL이 업로드 되는 것을 막는 부분이다.// # 뒤의 문자열 시작이 https://이라면 Sorry~~...를 출력할 것이다.//*******검사부분*******if (url.match(/^https?:\/\//)) {setInnerText(document.getElementById("log"),"Sorry, cannot load a URL containing \"http\".");return;}// Load this awesome gadgetscriptEl.src = url;// Show log messagesscriptEl.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);}//getGadgetName함수의 반환값은 #뒤의 값을 가져와 반환한다.//window.location.hash는 URL 뒤의 값을 가져오란 의미//substr(1)로 인해 #이 제거된다.function getGadgetName() {return window.location.hash.substr(1) || "/static/gadget.js";}includeGadget(getGadgetName());// 부모 IFRAME과 통신할 수 있도록 하는 추가코드window.addEventListener("message", function(event){if (event.source == parent) {//inCludeGadget 함수 호출하는데 getGadgetName함수의 반환값을 인자로 한다.includeGadget(getGadgetName());}}, false);cs 주요 해석은 주석으로 달아뒀다. 요약한다면 #뒤의 문자를 로드하여 그대로 load한다. 필터링은 http 혹은 https로 시작하면 "Sorry, cannot load a URL Containing "http""라는 문자열이 출력되는 것을 확인할 수 있다.
우회법은 간단하다. javascript의 match의 정규식에서 대소문자를 구분하고 있으니 Https://로 시작하면 된다.
그러나 서버에 만든 js 파일을 로드하여 헀으나 아래와 같은 오류가 발생한다.
[문제 6 오류] 안전하지 않은 요청으로 인하여 차단되었다는 메시지이다. HTTPS를 통해 콘텐츠가 제공되어야 한다고 한다. 자가서명을 하는 SSL 서버를 만들어 통신하면 될 듯 하다.
다른방법이 없나 힌트를 찾아보니 'https://www.google.com/jsapi?callback=foo'라는 URL을 제공하고 있다.
foo인자를 alert로 바꿔주면 페이지의 맨 하단에 alert()가 기록된다.
마침 https이니 이를 이용하여 alert를 삽입하면 된다.
답: Https://google.com/jsapi?callback=alert
다른 사람들은 어떻게 풀었나 writeup을 찾아보니 data:text/javascript,alert('xss'); 라는 방법을 사용하고 있다.
Data URL! data: scheme가 접두어로 붙은 URL은 컨텐츠 작성자가 작은 파일을 문서 내에 Inline으로 추가시킬 수 있습니다.
총 4가지 파트로 구성되며 접두사인 data:, 데이터 타입을 가르키는 MIME 타입, 텍스트가 아닌 경우 사용될 부가적인 Base64 토큰, 그리고 데이터 자체이다.
data: [<mediatype>][;base64],<data> MIMETYPE에서 jpeg 이미지의 경우 'image/jpeg'이며, 생략한다면 기본값으로 text/plain;charset=US-ASCII가 사용된다.
변형하면 data:text/html,<script>alert('hi');</script>와 같은 형식으로도 사용할 수 있다.
※참고: 파일을 Base64로 인코딩하는 이유는??
종단간 통신에서 아스키문자가 아닌 컨트롤 기호등으로 오인받아 오류를 발생시킬 수 있기 때문에 시스템이 기본적으로 알고있는 128자의 문자로 변경한다!
'#02. 기존공부 > #02.3 웹해킹' 카테고리의 다른 글
XSS challenge 풀이[11-??] (0) 2019.04.27 XSS challenge 풀이[1-10] (0) 2019.04.13 XSS (0) 2019.03.29 DVWA 풀이 (0) 2019.03.12 root me 풀이 (0) 2019.03.12 댓글