1 example 0/4 challenges solved
Description
Ready for the full course?
Lifetime access of:
Next recipe
Polyglots: The Ultimate XSS Payloads
1 Example
0/1 challenges solved
All recipes
Hacking Websites With Cross-Site Scripting
1 Example
0/3 challenges solved
XSS Attacks From HTML Attributes
2 Examples
0/3 challenges solved
XSS Attacks From URLs
1 Example
0/2 challenges solved
XSS Filter Evasion
2 Examples
0/2 challenges solved
How To Use Event Handlers For XSS Exploits
2 Examples
0/3 challenges solved
XSS Attacks Inside JavaScript
1 Example
0/4 challenges solved
Polyglots: The Ultimate XSS Payloads
1 Example
0/1 challenges solved
How To Create Real XSS Exploits To Attack Websites
1 Example
0/3 challenges solved
How To Fix XSS Vulnerabilities In Code
0 Examples
0/3 challenges solved
How To Allow Safe HTML Injection
1 Example
0/2 challenges solved
How To Prevent XSS With Code Reviews
0 Examples
0/3 challenges solved
Automatic XSS Prevention
2 Examples
0/3 challenges solved
Exploiting Web Pages That Have A CSP
1 Example
0/2 challenges solved
Blind XSS
2 Examples
0/0 challenges solved
video transcript
Hello, world. I'm Jesse from Chef Secure.
Injecting into HTML isn't the only place XSS can occur, because sometimes JavaScript code can be vulnerable as well.
So you're going to need to understand where and how cybercriminals can launch their attacks from within JavaScript.
Now if you'll excuse me.
(pulls cookie out from beard and eats it)
Attacking XSS vulnerabilities in JavaScript requires you to be extra careful in maintaining proper syntax, so you don't cause any errors that'll stop your code from running.
In HTML you can often leave extra angle brackets and tags hangin' around, but JavaScript is way more picky, and will complain at EVERYTHING!
Strings are likely the most common place you'll find XSS vulnerabilities in JavaScript.
And you already know that single quotes and double quotes can be used to make strings, but backticks can be used in much the same way as well.
The only difference with using backticks to create strings is that they can contain more code inside them by using a dollar sign and curly brackets containing an expression.
From an attacker's point of view, this means that you don't necessarily have to break out of a template literal to inject code. All you need to do is surround your code with a dollar sign and curly brackets.
`${/* code */}`
But if you wanna break out like a normal string, you can still do that as well.
And, remember, since we're inside JavaScript, all the code has to be valid, because, if you introduce an error, then your attack's not gonna work.
One way to break out properly is to surround your payload with the right quotes or backticks, then just add + or - characters in between the original string, your payload and the final string you just created, and you now have perfectly valid JavaScript.
Strings are usually assigned directly to variables, but that's not always the case. Here are three other areas you might find strings in JavaScript.
Number one: function arguments.
You're already quite familiar with functions already. But they can have multiple arguments, each separated with a comma, and it's within these arguments that a vulnerable string can live.
For instance, open up a new console in your browser – doesn't matter where you are.
You can call the function, console.log
, with multiple
arguments
console.log(1, 'string')
and it will log 1 and the string to your console.
Number two: array elements.
Similarly, arrays can be created using square brackets containing comma-separated elements, which can also be vulnerable strings.
Back in the console, you can type:
[1, 'string']
And you see that you created an Array. The first element is the number 1, and the second element is the string.
Number 3: object properties and values.
Objects in JavaScript are collections of properties and their values. The usual syntax is: you have curly brackets surrounding a property name, a colon then a value. and each property definition is separated with a comma.
Now, you can have vulnerable strings in property names, but it's more common to find them in values.
So in the console, you can set a variable:
test={number: 1, name: 'string'}
And you see you've just created an object with two properties. The first is number with its value of 1. And the second is name with the value of 'string'.
As an attacker, in each of these situations your string injection remains the same.
In the console type in a set of single quotes for an empty string.
''
This is where you're gonna be injecting.
So type in your alert payload:
'alert()'
And then the next step is to surround the alert with the right quotes. So we're gonna surround the alert with another set of single quotes.
''alert()''
And then we're gonna add the + characters in between each part. Right here. And then hit enter.
''+alert()+''
And there was an alert in the browser.
However, let's say the + and - characters were being filtered out. What do you do then?
You are gonna need to write some JavaScript, and, practically speaking, it doesn't really matter what you do, as long as you don't cause an error.
For instance, go back to console.log. Type in:
console.log(1,'string')
So the string is what you're attacking, and you already know you need to break out and alert, so go ahead and do that right now.
Replace string with your payload:
console.log(1,''alert()'')
Since we're not gonna use + and - characters, let's just turn this part into three new arguments, by separating each part with a comma.
So we'll have a comma in between the first empty sting and alert, then another comma in between alert and the final empty string.
console.log(1,'',alert(),'')
Hit enter. And you'll see that the alert was again triggered in the browser.
Since JavaScript allows you to pass as many arguments as you want to a function, there aren't any errors here.
You can also do something similar for arrays and objects as well.
[1,'',alert(),'']
{number:1,name:'',x:alert(),y:''}
Another piece of JavaScript you're gonna need to know are comments.
Comments allow developers to add notes or documentation within code without interfering with the functionality.
To comment out a single line, just add two forward slashes.
For cybercriminals, comments can be used to take out pieces of code to make attacking it easier.
For instance, when injecting into a string like before, instead of adding an empty string after your alert, you can just comment out everything that's left over.
''+alert()//'
Multiple lines can be commented out as well starting with a forward slash and asterisk, and then ending the opposite way with an asterisk and forward slash.
/*
code
code
code */
Additionally, statements can be ended early by using semicolons.
'';payload;''
"';payload;'"
`';payload;'`
Let's try this out now. Open the JavaScript Injection example for this recipe below.
Okay, so we need to enter a username. I'm gonna type in Jesse, because that's me.
Click update.
That username is taken. How about Jesse116? I don't wanna be Jesse116. Cancel!
That username is taken. How about Jesse114? Okay. Sounds good.
Hi, Jesse114.
Okay, we need see how this is working. Right click and inspect the page.
There are two scripts at the bottom, so let's start with the first one.
Starting off first, there's a function, inputUpdated
Afterward, you can see the update button registers this function as its
click handler, so let's look at the details.
First off, there's a script variable set to the element with the id,
dynamic-script
. Next, there's a comment showing that the
next line simply deletes the script if it exists. Afterward a new
script gets created to replace the old one with the same id. Then its
contents are set with innerHTML
using a template literal.
Inside the template literal, there's a random number function, then an
input variable set to the value of your input, then this gets used to
create a nameSuggestion
variable by simply adding a random
number at the end.
Until the user accepts the name suggestion, a new one will be generated.
Finally, the name gets added as the textContent
of the
element with the username
id. This entire script is then
added to the webpage with document.body.appendChild
If you don't see it yet, take a moment to find out where the vulnerability is and how you might attack it.
The answer lies within the dynamic script that gets generated. Your input gets injected directly inside the input string without any protections.
So now's the perfect chance to use the string breakout attack I talked about earlier. See if you can do that without my help.
So like I said earlier, write your alert then surround it with single quotes to break out of the string. Then you can add pluses in between each part so there aren't any errors. Click the update button, and you'll see your alert.
'+alert()+'
Now since it didn't error, the page is still gonna run its code, so the undefined value that gets returned from the alert will be used for the name suggestion.
Similarly, you can also replace the last + sign with a semicolon and your payload will still work.
'+alert();'
And so will a comment.
'+alert()//'
'-alert()-'
HOLD UP!
You're an experienced attacker now, you can do better than undefined and NaN values.
I want you to write a payload so that you can call your alert, but still return a name that can be used for the name suggestion.
Easy mode is: you have a name and it contains undefined.
NAMEundefined###
But hard mode is: you only have a name.
NAME###
One final note is that your browser will parse HTML before running JavaScript.
So if you're injecting inside a script element on the page, but you can't break out of the string, don't give up because you can still have XSS. You can do this by closing the current script element with a closing script tag within the string. Then adding a new script tag will allow you to inject a new script.
<script>
let s = '</script><script>alert()//'
</script>
Now this doesn't work in this example, because the script is being added dynamically, but you'll have a challenge for this later.
Overall, the JavaScript context requires a bit more finesse when attacking, compared to HTML. But the vulnerabilities are still just as dangerous.
And, as you've seen, JavaScript will require its own special escaping but we'll go over that in another recipe.
For now, it's important to know the various pieces that make up JavaScript, so you know where vulnerabilities can live, and how they can be used to attack users and, possibly, steal their delicious cookies.