Author Of The Blog And Winner Of Spot The Vulnerability XSS Challenge November 2022: Given Ncube
One common vulnerability in web applications is Cross Site Scripting (XSS), which usually allows an attacker to take control of the victim’s browser, steal authentication cookies, and may sometimes lead to code execution on the backend server when chained with other vulnerabilities.
It is a type of vulnerability that allows an attacker to inject malicious code into an otherwise trusted website. This is usually because user input was not filtered, validated, and/or encoded upon entry. For a detailed introduction to XSS check out this article on OWASP. In the meantime, let’s take a look at the snippet below.
The snippet above features typical XSS protection in a web application. In this guide, we will go step by step on how to bypass it and how we would secure it. Before we start any exploitation, let’s first understand what the code does:
escape()
function is supposed to remove potentially dangerous characters from the string entered by the user..replace()
on the string which replaces prompt, confirm, or print with the alert..replace()
then removes all JavaScript special characters from the string.If we try to input any JavaScript shenanigans it just won’t work because there is protection, or is there?
First, let’s look at JavaScript’s string.replace() behavior.
According to MDN:
The replace(pattern, replacement) method returns a new string with one, some, or all matches of a pattern replaced by a replacement. The pattern can be a string or a RegExp, and the replacement can be a string or a function called for each match. If the pattern is a string, only the first occurrence will be replaced. The original string is left unchanged.
However, this function only replaces the first occurrence of a match. The rest of the string will be ignored.
This is exploitable!
Let’s craft our payload to pass to the input:
If we input prompt('pwned')
it will be replaced with alert'pwned')
Now, prompt()prompt
will be replaced with alert'pwned');prompt('pwned')
. See where this is going?
However, this will just throw a syntax error. So let’s try to assign the first prompt to a variable.
var decoy = "prompt('just messing with you')";prompt('oh I was not kidding')
Notice the double space between var and decoy, this is to make sure that the regex at:
searchString.replace(/[-[\\]{}()*+?.,'"\\\\^$|#\\s]/,"")
This code only replaces one space.
By the way, the space is matched by \\s This will return something like this:
var decoy = "prompt('just messing with you')";prompt('oh I was not kidding')
Since it is valid JavaScript code and appended in script tags, we now have XXS!
To remove the vulnerability from the above snippet we just have to use JavaScript’s string.replaceAll() which replaces all instances of a match in a string.
We are always posting such challenges. We also give rewards and shoutouts to winners of challenges. To participate in such challenges follow us on Twitter, Linkedin, and Instagram.
To increase the arsenal of your knowledge you can also check our latest blogs.