This may be obvious but XSS is one of my favourite vuleranbility types because of the depth and complexity. It all seems so super simple but when you really get down to the core of XSS there is a world of wonder to explore. Besides the different types of XSS ( Being reflected, stored and DOM — blind XSS is another form of stored XSS ) there are also a lot of different contexts which most people seem to glance over completely. Most courses and articles that cover XSS will only concern themselves with HTML injection but this is just a small part of what XSS is all about.
We will look at what it takes to look for all kinds of XSS attacks in all sorts of contexts but also at what we can do to stop this kind of attack.
What is XSS?
First we need to know why this vulnerability type occurs and we can state that this issue can arise wherever the developer takes user input and renders it onto the page without sanitizing that input. There are several ways to sanitise the input of which the safest but also most restrictive seems to be whitelist based filtering.
Whitelist based filtering is implemented by checking every single piece of user content and only allowing it if that user input is defined on a whitelist. As you can see this can be very cumbersome as we need to define every single input we want to allow which can give a lot of unforeseen issues.
For those reasons a blacklist based filtering system is often chosen where the input is filtered if all or part of it occurs on a blacklist. This is a lot less safe though because if the developer forgets just 1 value on the blacklist they might be opening themselves up to major attacks.
What is the impact?
The impact of XSS really depends on a couple of factors. We need to check which context we are in, what cookies have the httponly flag and if there is any data we can steal on the page. All of these are just a couple of factors that determine the impact but to be complete we should name all the factors that can improve the impact of an XSS that we can think off. Be warned though that this is based on the limited knowledge of one rat so it might be a bit lackluster.
- Do the session cookies have httponly cookies? If you are a developer set these as they serve to protect cookies from the scripting context
- Can we steal data from the page? If you are a developer make sure that CSP is properly implemented on at least the pages that contain sensitive information. This is not an easy task as we might need to allow certain resources which might open us up to things like dangling markup injection.
- Can we execute sensitive JS functions? Remember that XSS can execute any JS function that is available to the current context so that means you might be able to execute a sensitive function such as DeleteAccount();
- Are we in an iframe or sandbox? This will limit any sort of data we can access and is usually pretty effictive against XSS if the seperation of data has been applied properly
- What context are we working in? After all if we are able to insert data into a hidden input field’s attribute value it might not be as impactful as being able to insert a script tag on a page. This is because hidden input fields can’t grab focus easily so they can’t really trigger any JS handlers without user interaction.
- Can we simply steal any data without having to execute danling markup injection?
- Can we steal CSRF tokens and chain XSS into CSRF?
- If we have self-xss try to upgrade the severity by chaining it with a CSRF issue where the server does not check the CSRF token properly thus allowing you to insert your xss attack vector into someone else’s account.
How to test for XSS
For our passive method it’s a matter of testing every single input field or reflected value that you see. I can not stress this enough! This means input fields, headers, … anything you can think of you need to test it. Just enter the value and move on to explore the functionality. Don’t dig too deep yet, in this phase we just want to seed our attack vector as far as possible. We want to have it in every possible database field and the reason is that when later on the application needs our data, it will grab an XSS attack vector and that means we are automatically testing for XSS and all we had to do is make our name, last name, adress, … into a simple XSS attack vector when we registered. We are automatically testing every single location where the target needs that name and that is gold for us.
The only disadvantage of this method is that it’s not very accurate and you will miss a lot of good attack possibilities in this way but it’s so much better than blindly entering just any attack value in some of the fields.
'"><img src=x><b>RAT+IS+HERE_GIMME'" I am testing for JS context injection
'"> I am testing for html tag attribute injection
<img src=x> I don't know why but images don't seem to be filtered as often as other attack vectors
<b>RAT+IS+HERE_GIMME Obvious HTML injection attempt. What's special is that i will use this value later.
This is where our value RAT+IS+HERE_GIMME comes into play. I will start looking for locations where this value is reflected.
- The HTML context might straight up reflect the name which might expose an entry point for us again.
- The HTML tag attribute might reflect our name into a value attribute from an input field.
- The value might be reflected in the DOM
- The value might be reflected in the angular context
I think you get the point by now. There are so many possible contexts of reflection and every location of reflection has it’s own attack techniques. We will need to
- See which characters are filtered
- If we can attack the system without using those filtered chars
- If we can get around the filter for the forbidden chars
- How our value is reflected and how we need to attack it. For example if our value is reflected between single quotes we will need to insert single quotes somehow into the reflection.
And if all of this wasn’t enough yet we also have to find out what impact our attacks will have. In the chapter”What is the impact?” we go deeper into how we can abuse these vulnerabilities.
Types of XSS
We already talked a little bit about the different types of XSS but i think it helps if we go over them fully to explain the differences to you and to show you what kind of testing is expected of you as an ethical hacker because we will also be discussing the small differences in test objectives between the types of XSS.
This is by far the most popular type of XSS out there and a lot of hunters and pentesters will focus on this as it’s the easiest to test for. You don’t need to know the application all you have to is look for reflected values which makes this vulnerability type a little bit less useful to me. I like to get to know my application and find all the input fields that store data in the database (which would be stored XSS) but i can certainly understand the appeal here.
For reflected XSS we are going to test every single parameter by entering a random value into that parameter and seeing if it’s reflected anywhere in the response. This can be the JS, the HTML, the DOM,…
My attack vector
When we find a reflected parameter we don’t have an XSS yet. All we’ve found is a reflected value on our page but it might be filtered properly or sanitised. What we need to now is to see where it is reflected and craft a proper attack string for that context. For example if you are stuck in a JS context where your input is surrounded by single quotes you will have to find a way to insert your own single quote into the attack string (which will often be filtered so you have to try and get around those filters). Next you will have to craft a proper attack to either steal data or execute a function or do something useful. Remember that a popup is just a bit annoying but it has no real impact so don’t just report alert(document.domain) please.
Stored XSS takes a bit more knowledge of the program to execute succesfully since you will have to test every single input field that you see. This is a GIANT task and it seems impossible but it’s needed for sure. In bug bounties there will be no low hanging fruit. That will all be picked clean by pentesters already. Our amazing co-workers already did part of the work and now it’s up to the bounty hunters to find that one field that everyone overlooked in their security measures.
I use the same attack vector as always and i just start. I put on some music and i register and every single input field that i see gets an attack vector thrown at it. Make sure you test everything. Look at every link on every page and actually look for hidden links as well. You can find those in JS files often because developers will put calls they are testing in the JS file and simply not call it from the production application but it’s still available. This is usually a dream as we can test for things like XSS on pages that others hunters haven’t even seen yet possibly.
Blind XSS is also part of stored XSS as we try to insert an attack vector and a third party will open that attack vector via a system that we can not access under normal working conditions. This can be the back-end website of a ticketing system for example or a chat bot.
For this you need an out of band server. I use https://xsshunter.com/ You can set up your own out of band server from here. Then we need to make an attack vector that will call back to our JS script.
There are ofcourse more payloads depending on the situation but i have a list of them.
If i can i just whack them all into a chatbot or ticketing system and hope for the best.
For this chapter i am going to have to point you towards my XSS course as this is a bit too complicated to explain in simple terms and i don’t want to duplicate my work on that either. I don’t really like duplication as when i need to change something i would have to change it on two places.
XSS into account takeover?
Something i’ve been asked several times is how XSS can lead to account takeover so i will attempt to explain this here. When we execute XSS, we usually test with an alert() or something similar like a confirm(). When we see that popup our hearts go racing ofcourse as they should but this is just the start of our journey.
In the impact chapter we already talked a little bit about what we can do when we have an attack vector that seems to work but a lot of people still seem to be a bit confused on how you take over an account with that popup. This is ofcourse not possible via that popup but we can perform some other actions to steal the cookies for example and then we can enter those into our own browser and pretend to be our victim.
- First we need to steal the cookie. If this is not possible account takeover will be harder.
- If this is not possible because of the httponly flag for example we might still be able to execute a JS function that changes the email adress. All we have to do is change the email adress of the victim to ours and request a password reset.
- If we can steal the cookie we will have to make a request to our own webserver and pass the session cookie that we need as a GET parameter.
- We can then see in our access logs of out own server that a request had been made that contained the cookies
- We then need to edit our own session cookie to the value of our victim and if everything went okay we are now browsing the target as our victim
There are several other ways such as
- Stealing a CSRF token and changing the email adress in that way to change the password
- Changing the password if the server doesn’t check if the old password is correct
So how do we prevent it?
Now that we know how XSS attacks occur and what impact they can have we can follow a few key guidelines to defend ourselves from XSS attacks. These will not give full XSS protection, there is nothing that can that.
- Make sure you have a good usage of the SOP and that you don’t allow unwanted calls to other servers which are unkown.
- Make sure your CSP headers are set properly and that they do not allow for unknown domains to execute scripts on your server
- Make sure you sanitise user input. Look up how to do that in the language you are using.
- PHP: htmlspecialchars(input)
- Python: cgi.escape(‘malicious code here’), see: http://docs.python.org/library/cgi.html#cgi.escape
- aspx: https://docs.microsoft.com/en-us/aspnet/core/security/cross-site-scripting?view=aspnetcore-5.0
- Always mark important cookies with the httpOnly flag. This will prevent any JS from accessing the values in those cookies.
Some more information can be found here:
How to prevent XSS | Web Security Academy
In this section, we'll describe some general principles for preventing cross-site scripting vulnerabilities and ways of…
Where can we find more?
The XSS Rat
Does this course contain different content from Your Bug Bounty Course?Yes, this course includes some advanced…
There is an XSS course available and much more ❤ Thank you for reading!