Choosing a way of escaping JavaScript in ASP.NET

What is the correct way to escape JavaScript in C# / ASP.NET? For example:

<script>
var abc = '<%= def%>';
</script>
<div onclick="myfunction('<%= Xyz%>')" />

There are surely questions about this, but listing different options. There are

Results from these methods are not always the same and their documentation does not seem to clearly describe the use case.

In case of the latter example we probably should employ both HTML and JS encoding, I was able to exploit System.Web.HttpUtility.JavaScriptStringEncode when used without HTML encoding. However Microsoft.Security.Application.Encoder.JavaScriptEncode is so thorough that while I would still add HTML encoding to be proper, I can't see a way how it can be exploited.
JSFiddle: https://jsfiddle.net/1afn5dky/

Does each method have a preferred use case?

Upvotes: 3

Views: 745

Answers (1)

netchkin
netchkin

Reputation: 1384

The best answer for your specific usecase can be derived from OWASP Cheatsheet Rule #3

In general, this boils down to 1) the correct encoding actions and their order and 2) implementation.

Encoding actions and order here is fairly simple - you need to do javascript encoding. Beware the onclick use case though. If the function you mention is designed to execute code, you will probably need to come up with additional layer of sanitization. More information in this SO thread

As for the implementation, the owasp cheatsheet mentions now obsolete AntiXSS, which has been superseded by AntiXssEncoder class now present in .NET Framework and .NET Core. This can be used by HttpUtility class behind the scenes if you follow this setup in web.config, like so:

<httpRuntime ...
  encoderType="System.Web.Security.AntiXss.AntiXssEncoder,System.Web, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />

Without this setting, HttpUtility class uses HttpEncoder behind the scenes. (In your specific use case, JavaScriptStringEncode method is actually the same for both classes though).

In your first scenario:

<script>
var abc = '<%= def%>';
</script>

If def will evaluate to data rule 3.1 specifically recommends putting them into a separate element, evaluating them as a json string and then using json parser to read the data:

<div id="init_data" style="display: none">
 <%= html_encode(def.to_json) %>
</div>

// external js file
var dataElement = document.getElementById('init_data');
// decode and parse the content of the div
var abc = JSON.parse(dataElement.textContent);

If this is however impossible because def evaluates to a javascript function call, this approach is not possible. In this scenario, I think you need to change your design as codegen is usually a bad idea and you could have either do the full codegen on backend side or frontend (using an appropriate frontend framework). If for some strange reason you just cannot do any of these options, than you need to encode nested context (JS in HTML), and on top of that you also need to do sanitization of the resulting javascript calls.

Second example <div onclick="myfunction('<%= Xyz%>')" /> should be used with respect to rule 3, so HttpUtility.JavaScriptStringEncode should suffice. However, if your function executes the parameter, you should also sanitize it.

Upvotes: 1

Related Questions