XSS is an abbreviation for Cross-Site Scripting, a type of computer vulnerability normally found in web applications. According to Symantec, Cross-Site Scripting accounted for around 84% of all security-related vulnerabilities in 2007.
XSS is a type of attack on web sites where the attack vector is the web’s “Same-Origin Policy“. The attack attempts to trick your web browser into running code that will do something nasty (like steal your login credentials). A web browser’s security model is normally configured to only run code that originates from the site you’re visiting at the time. For example, this prevents a website like Facebook from sending code to your web browser in order to steal your credentials for Twitter. Your web browser will simply ignore the script’s attempt to read the cookies that are used for accessing Twitter. Facebook only has access to the data that originated from.. Facebook!
In a successful cross-site scripting attack, an attacker manages to “inject” nasty code into a website with the intent of having it run by the victim’s web browser. To take our previous example, the attacker slips some nasty code into Twitter that runs on the victim’s web browser. Since the code appears to have originated from Twitter, the malware has permission to steal the user’s Twitter login cookie. The attacker can now impersonate the user on Twitter and effectively steal their account.
It’s important to point out that in most cases the attacker is using a website’s flaw to steal client information. Specifically, security tokens used for password-less access to the flawed website. However, once the victim’s account is hacked the attacker can do further damage depending on what data can be stolen from the account; it could be billing information that allows the attacker to purchase things on the victim’s credit card, for example.
Types Of XSS Attacks
There are two types of XSS attacks:
- Non-persistent: The attack is performed in a way that does not require data on the server. Rather, a specially crafted HTML link is sent to an unsuspecting user in the hopes they will click on it. For example, Click here for cute puppy videos! You click on the link and then three hundred pop-up windows appear on your desktop. Or worse, nothing obvious happens but some private data is silently stolen.
- Persistent: The attack consists of a bad payload stored on an infected server. Each unsuspecting user who visits the site triggers the attack attempt. For example, a malicious user could tweak their Facebook profile so that when visited, a nasty script attempts to steal something from you. This isn’t normally possible with Facebook however, as they’ve created defenses for protecting themselves.
Which brings me to another important point; the internet is quite literally overflowing with badly written websites; some by very well known companies responsible for protecting sensitive data. I won’t mention any names here; but an online search referencing “Data Breaches XSS” will yield a lot of information.
The rest of this article describes a simple site that is vulnerable to an XSS attack.
Let’s look at a trivial example of a website that is vulnerable to a Non-persistent Cross-Site Scripting attack.
This is a simplified Home page that provides a password-reset option. The user is supposed to enter their email address.
<html> <body> <form action="Reset.php" method="get"> <h1>Password Reset</h1> <p>Enter your email address: <input name="email_address" type="text" style="width: 700px;"></p> <p><input type="submit" value="Submit"><p> </form> </body> </html>
This is the page that informs the user their password-reset request in now being processed. The user is shown the email address entered on the Home.php page.
<html> <body> <h1>Confirmation</h1> <p>A password reset link has been sent to the following email address: (<?php echo filter_input(INPUT_GET, "email_address"); ?>)</p> </body> </html>
The user is supposed to enter an email address. However, the Reset.php page has a flaw; it re-displays whatever the user entered on the previous page. If I enter normal text, everything works as expected. However if I enter HTML, the Reset.php page will display the result of the HTML; not the entered text itself.
For example, when I enter “<b>Hello</b> there” in the email address field, the Reset.php page will display the text as: “Hello there”.
What if the user enters the following text in the email address field (line breaks for readability):
When this code is “re-displayed” by the Reset.php page, instead of seeing the text you see this:
The user’s web browser will actually run the code when vulnerable to an XSS attack. The solution is simple in concept; always filter user input! However in practice, many programmers create applications without this understanding in mind.
The following HTML fixes the XSS vulnerability in Reset.php (see FILTER_SANITIZE_SPECIAL_CHARS):
<html> <body> <h1>Confirmation</h1> <p>A password reset link has been sent to the following email address: (<?php echo filter_input(INPUT_GET, "email_address", FILTER_SANITIZE_SPECIAL_CHARS); ?>)</p> </body> </html>
How This Works In Practice
The previous example isn’t very useful. We enter a script and it runs on our machine; nothing happening there is problematic. How does a malicious individual use this to attack someone else? By sending an unsuspecting user a specially crafted link that will do two things:
- Perform an HTTP GET method against a target susceptible to XSS (in our example that would be Reset.php).
The link might be sent in an email to the intended victim with a title that is enticing to click. “You’ve won the grand prize”, “Free vacation”, “Bankers hate this”, and so on. The link might be something like:
Wow! Boy I love boats! Wait.. hovering over the link I check my browser’s status window and see this:
Apparently it was all a big ruse.