ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 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')을 호출한다.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
     
          function chooseTab(num) {
            // 적절한 이미지를 동적으로 로드
            var html = "Image " + parseInt(num) + "&lt;br&gt;";
            // HERE ATTACK VECTOR
            html += "&lt;img src='/static/level3/cloud" + num + ".jpg' /&gt;";
            $('#tabContent').html(html);
     
            window.location.hash = num;
     
            // 현재 탭 선택
            var tabs = document.querySelectorAll('.tab');
            for (var i = 0; i &lt; 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 부분을 추출한 것이다.

    1
    2
    3
    4
    5
    6
    7
          function 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진수로 해석한다.

    사실 여기는 별 상관이 없다. 

    1
    <img src="/static/loading.gif" onload="startTimer('12');" />
    s

    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를 발견할 수 있었다.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
     
        function 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 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);
        }
       //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

    댓글

Designed by Tistory.