Analysis

Entering the site we see the following.

From the message we now know that there’s a parameter, html, that we might be able to use.

Checking the console output we see some errors.

Following the TypeError we see the following script.

<script nonce="d8076a5626ab21fc44157db490af97d6">document.getElementById('lock').onclick = () => {document.getElementById('lock').classList.toggle('unlocked');}</script>

So the error is caused by trying to set an onClick handler on a non existent element. A search in the source confirms that there’s no element with the id lock.

Moving on to the SyntaxError we see a more interesting script.

    <script nonce="c26d9dbad58116d983beeef9f628ad29">
      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>

Here we see that another parameter, xss, is being used to create a script element that is appended to the body element.

The interesting parts are that the parameter is being appended to )]}’ which is what caused the syntax error in the console.

We can also see that if the last element of the element with id body has the id intigriti, the last four characters of the last elements innerHTML is beeing prepended to the string.

Injection

Now we can start to test the parameters and see what happens. First, let’s start with the html parameter and see how the page behaves when adding this.

If we just enter some text, like challenge.php?html=test, we see that our input is reflected on the page.

Taking a look at the inspector to see where our text is outputted we find it in a h1 element. Here we also see the script tag that is added to the body element.

Now let’s create a div element with the id intigriti and try to make it the last element of the body.

Using the payload challenge.php?html=<div id='intigriti'></div> we see that we can inject html into the page.

Let’s try to to break out of the h1 and div tags.
Using challenge.php?html=</h1></div><div id='intigriti'></div> we see that we can close the parent tags. But our element still isn’t the last one in the body.

We need to find a way to remove the two last div elements. If we try an open element we can trick the browser into parsing the two existing elements into our element.

Using the payload challenge.php?html=</h1></div><div id='intigriti'><div we now control the last element in the body.

Now we see that the created script element has four additional characters which we should be able to control. If we change the payload to challenge.php?html=</h1></div><div id='intigriti'><div><a'a we get the following script.

And now the error in the console has changed to the following.

Now let’s add the xss parameter and try it out. Since we already have an expression in our script we need to add a ; at the beginning of our JavaScript. And when we add &xss=;alert(document.domain) to our payload we get an alert.

So our final payload is challenge.php?html=</h1></div><div id='intigriti'><div><a'a&xss=;alert(document.domain)