Introduction
This is part 2 of my series Secure your ASP.NET Applications. In this article, I will describe what exactly Cross Site Scripting (XSS) is and how a hacker exploits it and how we can prevent XSS attacks.
Background
Part 1 of this series is available here which is about how to secure your ASP.NET applications from SQL injection attacks.
Cross Site Scripting (XSS)
Cross-Site Scripting is a kind of security exploit in which the attacker inserts malicious code of his choice (mostly script) into a web page or a database without the user's knowledge. XSS in itself is a threat which is brought by the internet security weaknesses of client-side scripting languages, with HTML and JavaScript (others being VBScript, ActiveX, HTML, or Flash) as the prime culprits for this exploit.
We can categorize XSS as follows:
- Reflected (when malicious code goes from the user's browser to the server and comes back from server)
- Persistent (when code remains stored somewhere, example - code stored in a database and executed on the client browser over and over, which makes it more dangerous).
- DOM based XSS attack (both reflected and persistent can fall in this category, attacker can manipulate DOM elements and can use DOM data).
What can these attacks do:
- Create and access DOM elements
- Send information to attacker site
- Hijack cookies, click events, credentials
How is it exploited
Following are the ways an attacker tries XSS on a web application:
- It can be done from server side code (example: ASP.NET code)
- It can be done from client side code (JavaScript/jQuery code)
- Attacker can inject script into user's experience
1. Reflected Cross Site Scripting Attack
In this kind of attack, the attacker generally tries to send script or HTML input to the server and lets it come back to the browser and run. They achieve it using a querystring. Although all latest browsers apply XSS filters, HTML elements can be inserted using this attack. Also to test, you can enable XSS filters in browsers; for IE - Tools > Internet option > Security tab > Custom level > Enable XSS filter. Let's see how to do it so things will be more clear:
I
n the above example I simply pass the HTML in the query string which gets reflected in the web page. This is just to show the attacker can use proper scripts with intention to get your credentials.
In the above example we are passing an HTML element and script in our label which gets assigned as it is and becomes a legal script, and the element for a page gets reflected in our page and shows the effects. This is just a basic example of how an attacker tries Reflected XSS, scripts, and their use can be too harmful.
2. Persisted Cross Site Scripting Attack
In persisted attack, the user injects a script to the database and every time the user visits that page he faces the consequences of that script. Example:
Script injected in the Comments section:
hiii this is text
<link rel="stylesheet"
href="http://code.jquery.com/ui/1.10.3/themes/smoothness/jquery-ui.css" />
//these scripts are innocent (Just opening the pop up),
//that's the developer cause who developed vulnerable web applications .
<script src="http://code.jquery.com/jquery-1.9.1.js"></script>
<script src="http://code.jquery.com/ui/1.10.3/jquery-ui.js"></script>
<script>
$(function() {
$( "#dialog" ).dialog();
});
</script>
<div id="dialog" title="Session Out please login again">
<input type="Text" placeholder="login"/><br/>
<input type="Text" placeholder="login"/><br/>
<button>
3. DOM based Cross Site Scripting
Both persistent and reflected can fall in this category, but some other variances of attacks make it different. Some developers do think JSON is safe and some use jQuery unsafe methods. How they use it:
//Encoded String using Microsoft.Security.Application.Encoder.JavaScriptEncode
var json = jQuery.parseJSON('{"name":"sarvesh",
"girlfriendname":"\x3cscript\x3ealert\x28\x27hehaha\x27\x29\x3c\x2fscript\x3e"}');
var createelement = document.createElement('div');
document.body.appendChild(createelement);
//we should not use this html , we can use text instead of this
$(createelement).html(json.girlfriendname);
//it will show the alert
As attacker is not inserting a direct script, he is inserting an encoded string which contains a script. These are new ways an attacker finds to exploit XSS. Or we can use a direct encoded string, I just use JSON to show this; this is also not a safe way.
var jencoded = "\x3cscript\x3ealert\x28\x27hehaha\x27\x29\x3c\x2fscript\x3e";
//this will give the same result
Another way of attack comes under this category, i.e., using HTML elements and JavaScript code without a script tag. The developer tries to find the script tag or <> these characters and replace them to avoid XSS but that is not a full proof way. The following example shows that.
Sometimes we need to show a dynamic alert:
<img onmouseover=alert(user input) />
The user can give input in a SQL Injection manner like this:
<img onmouseover=alert(1) onmouseout=alert(document.cookie) >
Now he can see the cookies you are saving, and that might be user credentials or any important data.
How to prevent XSS
- Your code output should be HTML encoded but make sure while storing data, it should not be encoded. Encoding and storing can lead to double encoding.
- Specify page encoding in web.config because the attacker can change the encoding to UTF-7 which has a different standard to write the lines and can make it tough to filter out the script code in the page.
- Apply content security policies to allow the script of your own host, or to allow the script of any host like Google and Microsoft. We can add a header to stop scripting from the attacker site or we can use a third party site.
- Do not use filter approach to find the script tag and replace that, there are many cheat-sheets available on the internet for XSS. A simple example that an attacker can use:
onload=alert('anything')
. - Data validation: you can trust the user input, just make sure the data is exactly what your application expects.
- Don't set the
ValidateRequest
attribute to false. When it is true it might throw an error; to prevent this error make sure your data is properly encoded before sending it to the server. - Be concerned where DOM elements are being created and modified. Use functions such as
setAttribute
anddocument.createElement('div')
rather thandocument.writein
and$('div').html()
. - Force the user to update IE 6 which is very much vulnerable to XSS. IE6update.com is a better solution for that.
- Audit every place where data is assigned. Know your control behavior as a label can't post the values and text-box can. So better encode text-boxes first. You can use a third party control to check the vulnerability; for Firefox use XSS-ME and for Chrome can use DOM-SNITCH.
- Update yourself on regular base checks, new ways of the same attack. The attacker invents new ways to do the same attack in their spare time. OWASP has a very good cheat sheet and defense for XSS. OWASP has regular updates about these attacks.
- Know ASP.NET encoding ways and use proper config statements to make changes.
< => < => &lt; => &&lt;
So for encoding we can use AntiXss sanitizier's
GetSafeHtml()
and GetSafeHtmlFragment()
. To download AntiXss, go to MS Visual Studio's Tools > Library Package Manager > Package Manager Console > Install-Package AntiXss.Sanitizer.GetSafeHtmlFragment(YourString)
It's better to use these methods if we really don't encode data.
<configuration>
<system .web="">
<globalization culture="en-US" fileencoding="utf-8"
requestencoding="utf-8" responseencoding="utf-8" uiculture="de-DE">
</globalization></system>
</configuration>
Although it is not full proof because IE does not support this, but we can still use this as an additional thing to stop XSS. Add the following code to allow scripts just from your host.
Collapse | Copy Code
Response.AddHeader("X-WebKit-CSP", "default-src 'self'");
// experimental header introduced into Google Chrome
// and other WebKit based browsers (Safari) in 2011
Response.AddHeader("X-Content-Security-Policy", "default-src 'self'");
//experimental header introduced in Gecko 2 based browsers
// (Firefox 4 to Firefox 22, Thunderbird 3.3, SeaMonkey 2.1).
All the above mentioned methods are useful to prevent XSS attacks.
Source Collected from codeproject.com
No comments :
Post a Comment