logo

Jesse's Blog

Congratulations! You've Won?

Congratulations! You've Won?

— 2024-07-29 —

Note:
  • This article was originally posted on my other blog.

Introduction

After taking a break for a while to work on other projects, I realised that I still had a couple of articles ready to publish that were waiting for issues to be fixed. This one took a little while but the issue is now patched and no longer exploitable.

What do you get when you allow the users of your website to change how the website looks in a fundamental way? That’s right, this post is all about our old friend, cross-site scripting. If you're getting tired of reading about this kind of issue, I don’t blame you! XSS is a common vulnerability but it’s not often exploitable and can require a great deal of creativity or other vulnerabilities for it to be useful to an attacker.

Anyway, today’s post is all about a bug in the search bar of a popular New Zealand retailer. I'll also demonstrate how this bug could have been used to trick users into offering up their personal information.

The Search Bar

Like all retail websites, users can search for products using a search bar. In the case of this particular website, when searching for a product your search term will be echoed back to your browser with a preview of the top matches:

A regular search term showing a popup window with search results.
A regular search term showing a popup window with search results.

From a UX standpoint, this is a really nice feature as it allows a user to preview the kind of results they would get if they were to submit the form.

XSS via the Search Preview

However, the implementation of this feature contains a glaring error: the echoed search term in the preview window isn’t HTML-escaped. We can see this when we type something like <em>123123123123</em> into the search bar and preview it:

The user’s search term is echoed back to them without being HTML-escaped.
The user’s search term is echoed back to them without being HTML-escaped.

As you can see, the text is rendered italicised, which is an indication that the em tag I wrapped by text in wasn’t escaped properly. However, although we have an XSS bug, it wouldn’t really be possible for an attacker to use it for anything malicious since they would have to instruct the user to type the HTML snippet into the search bar. I suspect that if they can get a user to do this, they likely have better methods of getting this user’s information.

In short: this is a bit useless.

XSS via the Search Results

Let’s continue with our investigation and see what happens when we submit the search term to view the results.

The user-supplied input is echoed back twice.
The user-supplied input is echoed back twice.

We can see that the user’s search term is echoed twice in the search results: once escaped (green) and once not (red). Not only is the search preview vulnerable but also the actual results page. And unlike the other bug, this one is actually useful to an attacker because, as you will see later, we can share the URL containing our XSS with unsuspecting victims.

How Bad Could It Be?

We know we can get em tags rendering correctly and we can assume that other text tags will also work (h1, strong, and friends). Let’s see what the limitations of this attack vector are by trying different kinds of HTML tags.

Images

One of the next tags I like to check to see if it works is the humble img tag. I like to check this early on because images can be an important springboard to getting scripts working if the system doesn’t block scripts properly. And, as you've probably noticed from some of my other posts, I have a favourite go to image saved as a bookmark in my browser.

Let’s try and search for the image tag:

<img src="https://i.kym-cdn.com/photos/images/original/000/581/296/c09.jpg" />

Successfully injecting an image via the search form.
Successfully injecting an image via the search form.

What a fine fellow! It’s encouraging to me that we can insert images into the page.

Scripts

The next step is to see if we can get JavaScript to execute on the returned page. There are a number of reasons why this might be an important goal for an attacker:

The reason that a script can do all of these malicious things is that the web browser can’t tell an evil script from a good one. If a script is being served from a website then the web browser will trust it.

I tried several different methods of injecting JavaScript via the search bar, including:

Unfortunately for an attacker, but fortunately for the customers of this website, all my attempts were in vain. The HTTP requests that my browser was sending were all blocked by a web application firewall (WAF) on the server.

The plain page returned by the WAF.
The plain page returned by the WAF.

It appears that the denial comes from a system called Edgesuite which I believe is a WAF owned by Akamai. Unlike Cloudflare’s WAF, I couldn’t find a way around Edgesuite. That’s not to say that there isn’t a way around it, nor is this an endorsement of Edgesuite or WAFs in general; your software shouldn’t be vulnerable in the first place.

With that in mind, if we're going to get a user’s personal information, we'll have to get a bit creative.

Going Phishing

Even though we can’t insert scripts into the search form, we can do pretty much anything else we like. It also doesn’t appear as though there’s any limit to the number of characters that can be submitted into the search form. Let’s use these properties of the XSS vulnerability to craft a convincing web page that brings the user to our malicious website.

I've come up with the following HTML which does exactly this. Currently, it just links to this blog but you could imagine that an attacker might link it to one of their websites that attempts to get information from the user.

<div id="hacks">
    <h1>🎉 Congratulations 🎉</h1>
    <h3>You have won our prize draw!</h3>
    <p>
        Click <a href="https://jesse.hacks.nz">here</a> to claim your prize!
    </p>
    <style>
        .error-custom-result-label, .no-search-result-title,
        .breadcrumbs.row, .error-custom-result-total,
        .main-search-container, .search-guidelines {
            display: none;
        }
        .error-custom-result {
            font-size: 0;
        }
        #hacks {
            font-size: inherit;
        }
        .error-custom-container {
            text-align: center;
        }
    </style>
</div>

And if we paste that into the search bar, we get this:

A somewhat convincing phishing attempt that tries to get the user to follow a link to a different website.
A somewhat convincing phishing attempt that tries to get the user to follow a link to a different website.

Because the search term is present in the URL of the resulting page, we can share this URL to anyone that we would like to phish. If we were to share this URL with a victim, it would look something like this:

https://www.website.co.nz/search?SearchTerm=%3Cdivid%3D%22hacks%22%3E%3Ch1%3E%F0%9F%8E%89Congratulations%F0%9F%8E%89%3C%2Fh1%3E%3Ch3%3EYouhavewonourprizedraw%21%3C%2Fh3%3E%3Cp%3EClick%3Cahref%3D%22https%3A%2F%2Fjesse.hacks.nz%22%3Ehere%3C%2Fa%3Etoclaimyourprize%21%3C%2Fp%3E%3Cstyle%3E.error-custom-result-label%2C.no-search-result-title%2C.breadcrumbs.row%2C.error-custom-result-total%2C.main-search-container%2C.search-guidelines%7Bdisplay%3Anone%3B%7D.error-custom-result%7Bfont-size%3A0%3B%7D%23hacks%7Bfont-size%3Ainherit%3B%7D.error-custom-container%7Btext-align%3Acenter%3B%7D%3C%2Fstyle%3E%3C%2Fdiv%3E

All in all, this is kind of bad. It would take a bit of extra effort for a malicious actor to take advantage of a user but it would likely be worth it.

Disclosure

I discosed this vulnerability to the company in question via a contact form on their website on the 20th of April (ayyyy). I didn’t get a response back from them.

Four weeks later, on the 17th of May, I reached out to them again via the same contact form. However, this time I mentioned that I would publish a blog post about it within the next week. I heard back immediately that they would investigate and that if I could please hold off on the blog post while they fix it. I agreed and didn’t publish the blog post.

At some point over the next 2 months they managed to get this issue fixed because as of the 20th of July, the issue is no longer present.

The vulnerability has been fixed.
The vulnerability has been fixed.

As you can see, the search term is correctly HTML escaped, rendering the XSS vulnerability non-existent.

Cover photo by Giorgio Trovato on Unsplash