Cross Site Scripting (XSS)
Cross Site Scripting (XSS) is an attack where a malicious attacker injects executable code (often JavaScript) into another user's browser.
Rather than target the victim, the attack exploits a vulnerability in the website that is visited, using this to deliver the malicious JS. To the victim, the JS appears to be a legitimate part of the website, and therefore should be executed without the site owner's (or victim's) knowledge.
How it works
Malicious JS is injected into one of the pages on a website, which implies that the site will accept (and include) user input in its pages. Again this goes back to Rule #1 of Web Development (don't trust user input).
If the page performs inadequate sanitisation on the input, the data inserted by the attacker will be executed by the victim's browser.
As an example, consider the following PHP page, that relays data input in a form:
<html>
<?php
echo "<p>Form input was ".$_GET["input"]."</p>"
?>
</html>
The code assumes that the user will only input text. So if the user
input was Hello world
the output would be:
<html>
<p>Form input was Hello World</p>
</html>
However, if the user inputs JavaScript such as
<script>alert();</script>
the output becomes:
<html>
<p>Form input was <script>alert()</script></p>
</html>
When the Page is loaded by the browser the code contained between the script tags will execute.
Task
If you start up web trainer (This is under week SQL) You can try getting the payload to fire, in the reflected xss example
There are two things you should note when considering XSS:
-
When testing for XSS, we will tend to use alerts as out payload. They are non-malicious (although irritating), and will cause a pop-up to be displayed making it clear when an attack has succeeded.
-
Chrome and Internet Explorer have some forms of XSS detection built in, depending on the web development framework used there is an option to enable this using the HTTP header
X-XSS-Protection: 0
Warning
Do not assume this will always work, there are workarounds (and not all browsers are equal)
So what can the Bad Guys do with it?
Things like (but not exclusively limited to) - Session Jacking - Key Logging - Phishing
While executing JS in someone's browser may not seem that bad (for example, it is hard to get hold of files on the remote system using JS) there are other options that can take place outside of the browser.
- JS may have access to Cookie Data
- JS can send HTTP requests to other parts of the web
- JS can modify the HTML of the current page using the DOM
Again, while these may not directly lead to loss of data, it is possible to steal credentials (then log in as another user) to escalate the attack.
Info
Also... Google "JavaScript Bitcoin Miner" for an idea of the current trends in XSS payloads.
Preventing XSS
Our main way of avoiding XSS is to NEVER TRUST USER INPUT
Looking a bit deeper we have the following rules:
-
Filter input when you receive it.
Data that we receive (or store) should be filtered for potential issues. However depending on the application functionality we may have some limits here. While restricting all character formatting can help prevent XSS, it also reduces the user experience (For example, only allowing bold, italic or Emojis for formatting)
-
Encode data on output
The flip side of Filtering. We can also encode data when we display it. This will convert common HTML Tags to a "web safe" version. (For example
<
becomes%68
, meaning it will be displayed correctly by the browser, but not identified as HTML code)Again, what we allow here can be limited by the desired functionality.
-
Apply Browser based prevention
Turning on options like Content Security Policy (CSP) can help. However YMMV depending on browser implementation.
-
Disallow parsing for pages that shouldn't be HTML.
We can also set the "Content-type" of our pages, to match the expected output. For example, in API's we can set the type to "text/json" (or similar) to avoid possible XSS issues.
So while the answer is easy, make sure we sanitise all user input. However, this can be a lot harder than it sounds. Given that way the web deals with data driven applications, there is a lot of work needed to identify where this data may be.
Note
Also Input sanitisation is Hard. If you want to practice methods of avoiding common input sanitisation, I would recommend running through the examples at web for pentester
Filtering #filtering
We all like to code in different languages. So I am going to avoid making recommendations on filtering approaches.
For a development language of your choice, research filtering options.
- What is available in the language?
- Are there known limitations?
Comment in the Feed using the tag #filtering
on your findings
Note
If you are stuck for ideas, you may want to take a look at the following
- Pythons html functions.
- The Jinja Template Language HTML Escape Functions
Identifying areas where XSS may occur.
The first stage of finding potential XSS is the code audit. Here we look through the code, identifying:
- areas where the user supplies data.
- Areas where user supplied data is displayed.
This can include (but is not limited to):
- Usernames / Emails
- "Posts" by users
- "Messaging" between users
Important
Remember that the user has full control over the data being sent. You may think that the client side email address checks will stop non email inputs. But its easy to bypass these checks.
Don't just consider the "standard" front end functionality. While its obvious that we should pay a bit more attention to this. We should, consider other areas where user information might be displayed. For example admin screens showing other user data (for example user-agent / browser, PII)
We should then check the data-flow for this submitted data, and ask:
- Is the user input sanitised? - If not, WHY not?
- When does the sanitisation happen: - Before the data is stored - Before the data is displayed (In this case we need to check EVERY time the data is displayed)
- How does this sanitisation happen:
- Is it a library, check for known exploits
- Have we rolled our own sanitisation? Can we be sure It works.
Testing For XSS
Important
Perhaps it would be better calling this "Testing our Sanitisation Works Correctly"
Once we have identified areas where XSS may occur, We need to check all of the areas we have identified.
We can have two strategies for testing for XSS. Either manual testing or automated testing.
Manual Testing
Here we can go through each input and test it against a list of possible XSS style strings.
For example, in a simple case we could just try the classic
<script>alert("XSS DEMO")</script>
in every text entry box.
However, as we should be sanitising our data, hopefully a simple alert box payload wont show up. So we need to think of more imaginative ways of working around the problem.
Push the filters that are used. If its a library, we should be able to get some idea of the types of input that are accepted. If we are using our own forms of sanitisation, then again we can test they behave as expected.
Important
This is also where our insight into the code base will help us. We know the types of sanitisation that we are using. We should also have full knowledge of the frameworks etc. So we should be able to target the testing.
Note
Subject to the usual unit-testing "We Only Test what we expect" issues.
When it comes to testing manually, we can also take a leaf out of the automated testing book. There are some excellent lists of XSS payloads out there For Example Those in SecLists That we can use to check for XSS.
Note
Again Pay attention to the frameworks you are using. If we are using things like Markdown to allow users to format text, then it would pay to look at Markdown specific payloads.
Automated Testing
While the lists of payloads in places like SecLists are great, and can help us check against the more common forms of XSS. There are a lot of them, and it can be a PITA to type them all in.
We can use tools Like Burp Suite to automate testing for XSS. Running through payload lists (for example those from SecLists), automatically
As tools are up to personal preference: I have included some example tutorials if you are interested.
- Official Burp XSS Tutorial
- Another Tutorial on XSS with Burp
- XSSer tool in Kali
- XSStrike
Important
Again remember that automated scanning needs some human intelligence applied. While it can help us run through lots of potential payloads, we still should apply some thinking to the results.
Summary
In this article we have had our introduction to Cross Site Scripting (XSS). We have looked at what it is, why it occurs, and highlighted some methods for preventing (and detecting) it in our code
Task
Using the Web Trainer (In the Github under SQL injection), try to trigger an alert box. Try one of the automated tools described above to trigger the payload.