Intigirti 1221 XSS Challenge - Writeup by @isira_adithya

As usual, Intigrti released a new challenge by E1u5iv3F0x And, Finally this time I got the first blood on the challenge. Challenge is hosted at https://challenge-1221.intigriti.io/


Website Overview 👨‍💻

As mentioned in the instructions, We have to pop an alert at https://challenge-1221.intigriti.io/challenge/index.php?payload=

I was able to give payload parameter any value, and it was reflected in the HTML source But, it was well-sanitized. After some basic testing, I concluded that this is impossible for me to bypass. (IDK, if someone bypassed this thing, make sure to read others' write-ups too. 😉)

You can click the cracker to pull it apart, and you will see the following content after that.

Like other Intigriti challenges, I was about to check the JavaScript Source Code for DOM-based XSS issues. But, I noticed this comment in the HTML source.

Quick Note:- You have to use both payload and open parameters to see that comment.

https://challenge-1221.intigriti.io/challenge/index.php?payload=test&open=true


Finding a way to inject HTML code 👀

Since this was a nice hint, I decided to skip DOM Based XSS Checks.

I immediately added the Referer header to the request with the value <h1>test</h1>

But, it was encoded in HTML Entities. This was kinda odd to me, This is not the default or normal behavior of a web application.

So, something is going on in the back-end. The next thing I noticed is that the Referer header's value is decoded using URL Encoding and it was encoded in HTML Entities

So, basically this what happens in the back-end. Raw-Input -> URL Decode -> Encode in HTML Entities

I tried some xss payloads but had no luck because of the HTML entities. 🥲


Full-Width Characters 🤯

Normally, whenever I see HTML entities, it is a dead-end.

But since there was that special/interesting comment, I decided to dive deep into this.

Annnd, the First thing I used was Full-width Characters.

Take a look at some information using the below links.

  1. https://en.wikipedia.org/wiki/Halfwidth_and_fullwidth_forms
  2. http://xahlee.info/comp/unicode_full-width_chars.html

I used the (U+FF1C) character to test this.

We can convert this character to URL Encoded format using CyberChef.

So, I gave it a try.

And, It worked! I got a normal < character in the response.

So, I quickly made this proof of concept.

--%EF%B9%A5%0A%EF%B9%A4script%EF%B9%A5%0Aalert(document.domain)%0A%EF%B9%A4%2Fscript%EF%B9%A5%EF%B9%A4%21--

Now, we got a working payload. 🥳


Creating a Proof of Concept ⚒️

To create a Proof of concept,

You can use/host this simple HTML file.

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta name="referrer" content="no-referrer-when-downgrade" />
    <title>Proof of concept</title>
</head>
<body>
    <script>
        // Checking if the payload is in the URL Already
        if (document.location.href.includes("alert(document.domain)")){
            document.location = 'https://challenge-1221.intigriti.io/challenge/index.php?payload=Hope+you+had+a+Great+Christmas+Day%21%F0%9F%8E%84Thanks%20for%20reading!&open=on'
        } else {
            // If the payload is not in the URL, adding the payload.
            document.location = '/?--%EF%B9%A5%0A%EF%B9%A4script%EF%B9%A5%0Aalert(document.domain)%0A%EF%B9%A4%2Fscript%EF%B9%A5%EF%B9%A4%21--'
        }

    </script>
</body>
</html>

Hosted at Netlify - dazzling-chandrasekhar-97d22e.netlify.app

I think you can already understand the JavaScript part.

It makes sure that the payload is in the URL then it redirects the user/victim to the Intigriti Challenge page.

But, focus on <meta name="referrer" content="no-referrer-when-downgrade" /> line.

Browsers have this thing called Referer Policy, so by default web browsers don't send the full URL in the referer header for security reasons.

Here is a great article about this.

https://web.dev/referrer-best-practices/

This is why I included this line.

This line changes the browser referer policy to no-referrer-when-downgrade which sends the full URL with parameters.

That's it!

I reported this immediately to Intigriti and got the first blood on this challenge. 😎

Things to keep in mind 🧠

In my opinion, I don't think this is a common issue in web applications. But, it is always better to keep an eye on this technique too.

Most applications/programming languages don't normalize the user input.

Here are some functions in programming languages that normalize strings.

  • normalizer_normalize - PHP
  • String.prototype.normalize - JavaScript
  • unicodedata.normalize - Python

Hopefully, this will help you to identify some bugs in open-source code.

Another thing to keep in mind is that Browsers always sends the referer header's value URL Encoded.

So, it is kinda OK to write code like this today assuming people are using modern browsers. NOTE: Internet Explorer 11 users are vulnerable to this. But, who uses that??

<h3>You are from <b><?php echo $_SERVER['HTTP_REFERER']  ?></b></h3>

In burp, you might find this working like below.

DO NOT REPORT THIS WITHOUT A PROOF-OF-CONCEPT

Please verify before reporting.

Notice, in burp, I am using < & > but this is what the browser sends. (URL Encoded characters)

As you can see, modern browsers don't send RAW characters in the referer header.

I recently noticed a lot of burp false positives about XSS in Referer header, that's why I decided to mention this too. :)


Alternative ways to create the proof-of-concept.

Using the challenge website itself. (User interaction required.) Basically, you can visit the challenge page with the payload. Then if you submit the form again, web browser will send the payload in the referer header. This allows to get the payload working with some user interaction.

https://challenge-1221.intigriti.io/challenge/index.php?payload=test&open=on&xss=--%EF%B9%A5%0A%EF%B9%A4script%EF%B9%A5%0Aalert(document.domain)%0A%EF%B9%A4%2Fscript%EF%B9%A5%EF%B9%A4%21--

For example:
- Click here
- Then you have to submit the form again.
- This will trigger the XSS, but the impact is kinda low.


Thanks for reading!

Hope this was a good read. :)

I hope you had a nice Christmas 🎅🎄.

And, be safe out there.

Wear masks, sanitize yourself as much as possible. 🤝

Thanks!