Elezar Elezar - 3 months ago 60
ASP.NET (C#) Question

In ASP.NET 4.5, how should I encode a string to be used as a JavaScript variable, to prevent XSS attacks

I know of several ways to do this, but they all have some downside. Is there an "accepted" way of doing it, that is considered the best?

I used to use the

Microsoft.Security.Application.AntiXss.JavaScriptEncode()
which is great, but AntiXSS has been end-of-lifed because the encoder is now included in .NET as of 4.5.

However, for some reason,
System.Web.Security.AntiXss.AntiXssEncoder
doesn't include the
JavaScriptEncode
method.

There's
System.Web.HttpUtility.JavaScriptStringEncode()
, but it uses a blacklist method for encoding, so it's unlikely to be as good as a whitelist encoder.

And I've seen some recommendations to use
System.Web.Script.Serialization.JavaScriptSerializer.Serialize()
, but that just calls
HttpUtility.JavaScriptStringEncode()
.

So what's currently the best accepted, whitelist method for encoding values written out as JS variables?

Answer

If you wish to include JavaScript code within a <script> block like this:

<script>
var myVariable = '<%=thisIsWrong %>';
</script>

Then in this context HttpUtility.JavaScriptStringEncode should be used. This function also correctly encodes special characters, so if </script> was to be rendered in a script tag in an attempt to close the HTML script tag ready for an XSS attack, it would be rendered as:

\u003c/script\u003e

which is the correct encoding for JavaScript to understand it as </script>, but without the browser interpreting it as a literal closing script tag. Some naively written JavaScript encoding routines would not convert this because the sequence does not contain \, " or ' characters.

If you don't make sure that closing script tags are not rendered, then an attack like so is possible. Imagine this is the input to your application:

</script><script>alert(1)</script>

which the renders in the browser as

<script type="text/javascript">

alert('</script><script>alert(1)</script>');

</script>

and the browser will interpret the script tag ending at alert('</script> and simply execute what is in the new script tag.

With the JavaScriptStringEncode function this is safe as it is rendered as:

<script type="text/javascript">

alert('\u003c/script\u003e\u003cscript\u003ealert(1)\u003c/script\u003e');

</script>

which does not contain </script> for the browser to interpret.

There's System.Web.HttpUtility.JavaScriptStringEncode(), but it uses a blacklist method for encoding, so it's unlikely to be as good as a whitelist encoder.

Some of the other encoding functions in .NET do use blacklist methods, however in my own testing JavaScriptStringEncode seems to be ample.

The OWASP recommendation for JavaScript is

Except for alphanumeric characters, escape all characters less than 256 with the \xHH format to prevent switching out of the data value into the script context or into another attribute.

so you could easily write your own to comply with this.

Note that if you want to include code in attribute tags:

<a href="http://example.com" onclick="alert('<%=wrong>')">Click</a>

then the OWASP method means you don't have to take care of HTML encoding too (because no HTML characters with special meaning are actually output). Without (e.g. with JavaScriptScriptEncode) you need to HTML encode too.

Having said all this, a safer way is to approach it like the answer to my question Secure way of inserting dynamic values in external JavaScript files. Use data- attributes to place the dynamic values in the DOM (in HTML) and then use JavaScript to extract these values. This will prevent all JavaScript encoding headaches.

Comments