Reflected XSS into attribute with angle brackets HTML-encoded

Level: Apprentice

Today we will solve Portswigger’s “Reflected XSS into attribute with angle brackets HTML-encoded” lab from their XSS (Cross-site scripting) series.

This is what we know:

This lab contains a reflected cross-site scripting vulnerability in the search blog functionality where angle brackets are HTML-encoded. To solve this lab, perform a cross-site scripting attack that injects an attribute and calls the 'alert' function.

Let’s go! When we open the lab, we see that it’s a blog with several posts and a search bar at the top of the page. Since we know that there is a vulnerability in the search functionality, let’s enter something random there and see where our input is reflected. I went with the representation of my feelings when I first wake up in the morning: “aaaaaaaa”.

Let’s view page source:

Next let’s try out some symbols that we need for achieving XSS: angle brackets(<>), single quote (’), double quote ("):

We can see that in the first instance all of these symbols are HTML-encoded but in the second case, inside the input tag, only angle brackets are encoded, but single quote and double quote are not. Okay, we can work with this…

Something that often comes in handy when dealing with XSS is Portswigger’s XSS cheat sheet . Let’s try finding a payload that we could use inside the input tag. For that we need to choose “input”, “all events” and “all browsers”:

There are a lot of results, however not all of them usable in this case. Ideally I want to find something that is simple, can be used without angle brackets and is Chrome-compatible (since that’s the browser I’m currently using).

For example this onerror payload seems to meet the brief at first glance:

However, when we try it out (I will explain how to alter the cheat sheet payload for our needs below) nothing happens because the input tag already has a “type” attribute and adding a second one will not really help our cause:

So depending on the context this step might require a bit of trial and error to find what works, but that’s all a part of the process!

Next in my search for something simple, Chrome-y and bracket-free, I see this onfocus payload that looks doable:

Now, how to make this payload suitable? First we need to escape that morning “aaaaaaaa” feeling, which we can do by adding a double quote . Then let’s add the rest of the payload and encode the spaces into %20 (or well, we can let our browser do that for us) so our payload will look like this:

?search=aaaaaaaa"%20autofocus%20onfocus=alert(1)

Nothing happens and this is what the page source looks like:

We can see that we managed to successfully escape the value attribute, but since we did that we have one leftover double quote at the very end of the tag. Let’s try to fix it by adding another " before alert(1) so that alert(1) would then be between quotes.

?search=aaaaaaaa"%20autofocus%20onfocus="alert(1)

And now we have triggered the popup and the lab is solved!

Let’s check the page source once more to see what it looks like:

Now we can see that there are not leftover characters anywhere and everything is looking nice and clean.

Of course, this is not the only payload out there that works in this scenario. For example the following would also do the trick:

"%20onmouseover="alert(1)

However this one requires some user interaction to trigger XSS: someone out there needs to hover the mouse over the text in the search bar.

Well, that’s it for today!