Tuesday, October 28, 2008

Cross-site scripting and a simple solution

Most of us hardly give security vulnerabilities any consideration when creating a web-application. It's something that takes care of itself right? Mostly we get away with it because our applications may not be affected the moment it goes live. So it becomes a habit to ignore taking care of it.

But its a ticking time-bomb. Its strange because the cost associated with additional security considerations are negligible compared to the losses that can arise when the application is actually comprised!

One such vulnerability is XSS or Cross-site scripting. It comes out at number 1 for the second time running in the OWASP Top 10 2007 .

XSS accounts for 80% of today's Internet security vulnerabilities says one source.

First, let's learn about our adversary. XSS vulnerabilities can be categorized into three distinct types. Each of these can be exposed in a variety of ways - this is only limited by the imagination of the attacker.

  • DOM-based XSS vulnerability is when the problem exists in the page's client script itself. This shouldn't happen unless your web-application itself is hijacked by a malicious attacker who then adds script that attack "safe" standard local HTML pages (that are usually installed with most applications, including IE). What can be done about it falls more into the scope of a system administrator. The other 2 are our responsibility...

  • Non-Persistent or Reflected vulnerability is the most common type of XSS. This is seen easily when there are inputs by the client into a web-page and this is displayed on a page returned by the server. Basically, this would mean that only the user who makes the inputs are affected.

  • Then there's Persistent or Second-order or Stored XSS. This is when the impacted data is stored on the server (file/database/LDAP/etc) - it is the most dangerous kind as it can affect any user to whom the compromised data gets displayed to.
How does all that sound to those of us who copy/paste a few snippets to address XSS (add code to ensure that no < or > make it through our inout fields, etc.) - although the solution seems to be a matter of restricting user input (or our output), we are all not exactly security experts to know about the dangers (never mind that the experts themselves are having a tought time).

This is where we can use library/frameworks developed by those who know the range of attacks out there.

One such tool is Antisamy, an open-source free library from OWASP.
Antisamy can be used to verify that provided input (submitted by the user for example) does not contain any XSS vulnerability. It's highly configurable using XML files so that you can decide the amount of security you need for your inputs.
And the best part is that it generates user-friendly responses pointing out the vulnerability which can be shown to the user.

See below code showing how easy it is to use:
  /**
* @throws PolicyException
* @throws ScanException
* @throws IOException
*/
public static void testAntiSamy() throws PolicyException, ScanException, IOException {
// Create a sample input, inputString, that can have malicious code as well safe parts.
String inputString = null;
StringBuffer buf = new StringBuffer();
buf.append("This is all normal text.\n");
buf.append("But suddenly out of the blue...\n");
buf.append("An eveil laughter crackles in the cold night...\n");
buf.append("<SCRIPT>alert('HAHAHA');</SCRIPT>\n");
buf.append("Did you hear that??!!\n");
buf.append("No?\n");
buf.append("How about this twisted one: <SCRIPT>alert(\"HAHAHA\");</SCRIPT><SCRIPT>alert(\"HAHAHA\");</SCRIPT><SCRIPT>alert(\"HAHAHA\");</SCRIPT><SCRIPT>alert(\"HAHAHA\");</SCRIPT>\n");
buf.append("Or this eveil smile!!! <IMG SRC=\"javascript:alert('XSS');\" />\n");
buf.append("Its actually worse than the laugh right? Right?\n");
buf.append("\n");
buf.append("ok ok. Heres a normal smile <IMG SRC='javascript' />\n");
buf.append("Hows that!");
inputString = buf.toString(); // //readFile1("Antisamy/Other/SampleInput.htm");
System.out.println("Original input:");
System.out.println(inputString);

// Use the predefined Antisamy policy file and apply this on the inputString
Policy policy = Policy.getInstance("Antisamy/Sample_policies/antisamy-anythinggoes-1.2.xml");
AntiSamy as = new AntiSamy(policy);
CleanResults cr = as.scan(inputString);


// Display cleaned input using getCleanHTML() of CleanResults.
System.out.println("\nCorrected output:");
System.out.println(cr.getCleanHTML());

//Display the errors encountered in the input using getErrorMessages()
System.out.println("\nError Messages:");
System.out.println(cr.getErrorMessages().toString().replaceAll(".,",",.\n"));
}
Java Sourcecode to HTML automatically converted code (Java2Html Converter 5.0 [2006-03-04])
by Markus Gebhard markus@jave.de
Further information: http://www.java2html.de/

So it's just a matter of taking the input and validating it based on the rules specified in the xml file through the CleanResults class. There are so many useful methods in this class - get all the details by downloading javadocs (get the source too) alongwith the library (make sure you have not just the main Antisamy library but also the supporting libraries) and sample application configuration files from the Antisamy page.

Practically speaking though, Antisamy is best suited for you when you already have a server-side trip - so its easily used for type 3 XSS. For type 2, if you have a client-side only thing going on, then you have to consider the consequence of having a server round trip just for the validation...

Have a safer day at work (do share any inputs you may have).

1 comment:

  1. i keep having the problem of referencing the xml file

    Policy policy = Policy.getInstance("Antisamy/Sample_policies/antisamy-anythinggoes-1.2.xml");

    even if i put the whole path name, there's a problem. May I know is there any particular directory i should put the xml file?

    ReplyDelete

 
Superblog Directory