The right tool for the job, XSS edition


It is not very uncommon to see pages that include a “returnUrl” parameter, usually within authentication flows. At times, the browser will run some script (like a call to an analytics service) and then another script issuing a redirect (through setting location.href etc.)


There are also other cases where UGC can find its way into JavaScript blocks. People might want to have their script do fancy stuff with the page’s data.


var url = '<%=viewData.returnUrl%>';



var commenterName = '<%=viewData.newComment.authorName%>';


for e.g.



Now for the “stating the obvious”:

Just like any other UGC, this type of content must be sanitized to prevent XSS attacks.


Not to long ago I was called to do a security inspection on a web application’s codebase. During which, some very few XSS holes were detected using JavaScript injection. This was quite surprising to me, as I knew that all content injected into JavaScript was being sanitized by the team.

Digging further I found out that they did call a sanitize function on UGC, just not the correct function. What they did was to run a JSON formatter over the UGC string, a thing that was solving JS errors occurring from string quoting problems, but it did not eliminate malicious scripts.

The weird thing was that the team was already using the AntiXss library (which is a very aggressive, white list based input sanitation library for .NET), for html fragments. The library also have a JavaScript Encode function. Switching the sanitation function of the team from calling the JSON library to calling the AntiXss library fixed the problem for good.


e.g. code to demonstrate the difference between the methods:

static void Main()
    var ugc = "';alert('xss');'";

static void Render(string encoded)
    Console.WriteLine("var returnUrl = '"+encoded+"';");

The output from the above snippet is:

var returnUrl = '"';alert('xss');'"';
var returnUrl = ''\x27\x3balert\x28\x27xss\x27\x29\x3b\x27'';


There are a couple of things to learn from that story:

     Tweet Follow @kenegozi