Writeup for JanuaryXSS in intriger
2021-1-28 00:0:0 Author: hpdoger.cn(查看原文) 阅读量:4 收藏

In order to prepare for the coming interview-examination, I decided to write some easy writeups for practicing my awful English. This article is a begaining.

Pretty interesting challenge, not so hard as usual. After about 2 hours when i tried my way to solve the chall, I found a way to alert the flag in page. Meanwhile, there are some tricks during the soving process, and this writeup was made to record them

The challenge address: http://challenge-0121.intigriti.io/

To simplify the code, i remake the challenge at localhost

<code id="flag">THIS_FLAG</code>
<div id="popover"><p>We just hit 30,000 Twitter followers! Thank you!</p></div>
<script>
    window.href = new URL(window.location.href);
    window.r = href.searchParams.get("r");
    //Remove malicious values from href, redirect, referrer, name, ...
    ["document", "window"].forEach(function(interface){
      Object.keys(window[interface]).forEach(function(globalVariable){
          if((typeof window[interface][globalVariable] == "string") && (window[interface][globalVariable].indexOf("javascript") > -1)){
              delete window[interface][globalVariable];
          }
      });
    });


    window.onload = function(){
      var links = document.getElementsByTagName("a");
      for(var i = 0; i < links.length; i++){
        links[i].onclick = function(e){
          e.preventDefault();
          delete(window.origin);
          safeRedirect(e.target.href);
        }
      }
    }

    if(r != undefined){
      iter = "r";
      safeRedirect(r);
    }

    function safeRedirect(url){
      if(!url.match(/[<>"' ]/)){
        console.log(url)
        window.setTimeout(function(){
            if(url.startsWith("https://")){
              window.location = url;
            }
            else{ //local redirect
              window.location = window.origin + "/" + url;
            }
            window.setTimeout(function(){
              document.getElementById("error").style.display = "block";
            }, 1000);
        }, 5000);
        document.getElementById("popover").innerHTML = `
          <p>You're being redirected to ${url} in 5 seconds...</p>
          <p id="error" style="display:none">
            If you're not being redirected, click <a href=${url}>here</a>
          </p>.`;
      }
      else{
        alert("Invalid URL.");
      }
    }
  </script>

Firstly, As we can see in the code ,we are able to control window.r from passing a GET parameter like server.com?r
-w531

Then, the global properties document and window will be cleaned if document/window.$x instance of string and include the string: javascript

    ["document", "window"].forEach(function(interface){
      Object.keys(window[interface]).forEach(function(globalVariable){
          if((typeof window[interface][globalVariable] == "string") && (window[interface][globalVariable].indexOf("javascript") > -1)){
              delete window[interface][globalVariable];
          }
      });
    });

Finally the window.r will be used as paramater named url to splice the window.location and the tag<a href=$window.r>

-w1026

However, we fail to escape the label because the Waf matches <>"'
-w423

At the end, window.onload could operate until the style.display in window.setTimeout executed competely.window.onload need the Inline-blocks be totally loaded

window.onload = function(){
  var links = document.getElementsByTagName("a");
  for(var i = 0; i < links.length; i++){
    links[i].onclick = function(e){
      e.preventDefault();
      delete(window.origin);
      safeRedirect(e.target.href);
    }
  }
}

After glancing over the code, I made two conceptions via different sinks:
1、sink of <a>: If i could control the attribute href like javacript:alert(1), I will get a click xss.

2、sink of window.location: If i could control the paramater window.origin like javascript:alert(1), I will get a wonderful xss that wihout user interaction

The value of href is same as the window.origin,so i gave up the first idea anyway. Now, let us find a way to the second one

First of all, We could not control the window.origin via simple url request
-w495

Quickly, the Dom-clobbering came to my mind, and we have to find a way to delete the window.origin. Coincidently, the waf helped us do that and the server resolves the subdomains to root domain broadly which means javascript.xxx.com equal to xxx.com
-w1264

The delete condition is achieved, we are supposed to create window.orgin. Do not forget the tag <a> is partly containable. Although the waf filter out "|'|space, we still create new attributes through %09|%0a|%0d|
-w511

It is worth mentioning that not all the tags could be converted to string via toString() and few tags would call tostring() to return the attribute value in it. Here, tag <a> meets our demand both.
-w617

Another one more thing, if attribute href contains a complete url,toString() function will return the entire url. If href startwith normalstring, the function will return host+normalstring as result because normalstring is regarded as a relative path.
-w562

However, if href startwith protocol, it returns the full protocol value, nearly caters to our intention!
-w306

As a final step, we need to write javascript:alert(1) to the href attribute and bypass the waf url.indexof('javascript')>-1,
-w477

Got a complete utilize! The eventual payload here:

https://javascript.challenge-0121.intigriti.io/?r=Javascript:alert(flag.innerText)/%0aid=origin

文章来源: https://hpdoger.cn/2021/01/28/title:%20Writeup%20for%20JanuaryXSS%20in%20intriger/
如有侵权请联系:admin#unsafe.sh