First let's take a look at the biggest benefit to using ESAPI4JS - The ability to mitigate client-side DOM Based XSS attacks. This is something that no other framework that I am aware of is yet to tackle, and as such, I think that we will begin to see this vector being exploited more and more in the wild.
Let us start at the beginning.
What is DOM Based XSS?
Who better to answer that question, than the experts at OWASP?
DOM Based XSS (or as it is called in some texts, “type-0 XSS”) is an XSS attack wherein the attack payload is executed as a result of modifying the DOM “environment” in the victim’s browser used by the original client side script, so that the client side code runs in an “unexpected” manner. That is, the page itself (the HTTP response that is) does not change, but the client side code contained in the page executes differently due to the malicious modifications that have occurred in the DOM environment.- OWASP
The most common type of vulnerable code that this affects is code which uses the information that is in the
window.location
global object. Let's work through an example of the vulnerable code, and how it could be mitigated using ESAPI4JS.
<html> <head> <title>My Vulnerable Webpage</title> <script type="text/javascript"> var getParameter = function( name ) { var startIdx = window.location.href.indexOf( name ) + name.length + 1; var endIdx = window.location.href.indexOf( '&', startIdx ); if ( endIdx = -1 ) endIdx = window.location.href.length; return window.location.href.substring( startIdx, endIdx ); } var firstName = getParameter('firstName'); </script> </head> <body onload="function(){document.getElementById('nameplace').innerHTML = firstName; }"> <h1>Hello <div id="nameplace"></div>, Welcome to my Vulnerable Page!</h1> </body> </html>
If you were to hit this page with the following URL: http://host.com/vulnerable.html?firstName=Chris
The resultant page would display: Hello Chris, Welcome to my Vulnerable Page!
However, what if you were to hit this page with a URL that looked like: http://host.com/vulnerable.html?<sript>alert('xss');</script>
You guessed it! You will get a pretty little popup. So what you say, server-side XSS controls can mitigate that risk easily, and you would be correct, however, what if the url looked like this: http://host.com/vulnerable.html#firstName=<script>alert('xss');lt;/script>
If you said that server-side mitigation wouldn't catch this, you are right! When a browser sends a request to the server, anything after the '#' is not sent as part of the request, as this is meant for browser control to jump to an anchor in the page.
So how do we fix this problem? Simple with ESAPI4JS - the page could be rewritten as follows:
<html> <head> <title>My Vulnerable Webpage</title> <!-- Dependencies --> <script type="text/javascript" language="JavaScript" src="/js/esapi4js/lib/log4js.js"></script> <script type="text/javascript" language="JavaScript" src="/js/esapi4js/resources/i18n/ESAPI_Standard_en_US.properties.js"></script> <script type="text/javascript" language="JavaScript" src="/js/esapi4js/esapi.js"></script> <script type="text/javascript" language="JavaScript" src="/js/esapi4js/resources/Base.esapi.properties.js"></script> <script type="text/javascript"> org.owasp.esapi.ESAPI.initialize(); var firstName = $ESAPI.httpUtilities().getParameter("firstName"); try { // Will throw an exception if there are multiple encodings in the value firstName = $ESAPI.encoder().canonicalize(firstName); } catch (e) { $ESAPI.logger('VulnerablePage').warn( org.owasp.esapi.Logger.EventType.SECURITY_FAILURE, e.getLogMessage() ); alert( e.getUserMessage() ); firstName = 'Guest'; } </script> </head> <body onload="function(){document.getElementById('nameplace').innerHTML = $ESAPI.encoder().encodeForHTML(firstName); }"> <h1>Hello <div id="nameplace"></div>, Welcome to my Vulnerable Page!</h1> </body> </html>
We have successfully mitigated DOM Based XSS attacks against our vulnerable page. Of course, in the real world, the vulnerable code will not be *quite* as obvious in most places, but the resolution is still the same.
Let's move on to the next piece, using ESAPI logging. You probably noticed the call in the above section of code to
$ESAPI.logger
There are a few things to deal with when setting up logging for ESAPI4JS. The first is to pick your Logging framework. The Log4JS framework is used by the Reference Implementation and so that will be used for the first part of this demonstration. A subsequent blog post will discuss how to implement other logging frameworks into your ESAPI.
The first step is to setup your logging configuration. For the purposes of this example, we will only be setting up a single logger, and we will continue to use our vulnerable.html example from above. Without further ado:
Base.esapi.properties.logging["VulnerablePage"] = { Level: org.owasp.esapi.Logger.ALL, Appenders: [ new Log4js.AjaxAppender('/jsLog') ], LogUrl: true, LogApplicationName: true, EncodingRequired: true }; // Since we specify that we want the application name logged in our configuration, let us give our application a name: Base.esapi.properties.applicaton.Name = 'Vulnerable Application';
Now this will POST your log entry to the path /jsLog which should be mapped to some handler servlet or php controller on the server side. More details on using this appender can be found here
Now any calls to
$ESAPI.logger('VulnerablePage')
will go to this logger.There are six methods for logging (trace, debug, info, warn, error, fatal) each with the signature
.method( org.owasp.esapi.EventType eventType, String message, Exception exception );
You can define custom event types by instantiating new instances of the org.owasp.esapi.Logger.EventType class or reference the static predefined events
- org.owasp.esapi.Logger.EventType.SECURITY_FAILURE - Used to log when something fails to pass a security control
- org.owasp.esapi.Logger.EventType.SECURITY_SUCCESS - Used to log when something passes a security control
- org.owasp.esapi.Logger.EventType.EVENT_FAILURE - Used to log when something fires an event, and that event does not complete successfully.
- org.owasp.esapi.Logger.EventType.EVENT_SUCCESS - Used to log when something fires an event, and that event completes successfully.
Creating a custom EventType is simple.
var customEventType = new org.owasp.esapi.Logger.EventType( "Custom Event", false ); // ... later $ESAPI.logger('VulnerablePage').info( customEventType, "Something happened!" );
HTTPUtilities
The HTTPUtilities object is meant to provide shortcuts for doing common tasks that have to do with the browser and the response. Right now, the available methods are:
- addCookie( org.owasp.esapi.net.Cookie cookie )< - Adds a single cookie to the cookie jar/li>
- getCookie( String name ) - Gets the String value of a cookie
- killCookie( String name ) - Deletes a cookie if it exists in the current cookie jar
- killAllCookies( String name ) - Removes all the cookies from the current cookie jar
- getParameter( String name ) - Gets the value of a parameter on the URL
This should be enough to get you started using ESAPI4JS. I will make a seperate post at a later time going over the i18n framework.
Enjoy and feel free to share comments!