Urgences 24 sur 7 – (888) 287-5858   Connexion au Portail TitanSupport    Contactez-nous      Blogue

As a follow-up to the conference given at Confoo a few weeks ago, we are doing a focus article on the same topic. The presentation was giving an overview of the modern XSS attack vectors and filter bypass. In this blog post, we will take a closer look at XSS in the context of .NET applications.

This article is intended to be a simple checklist for ASP.net MVC developers or security auditors. Defensive measures can be put in place at various layers including the template files (Razor or ASPx Forms), the Request Validation feature and the client-side (browser) filters.

 

Template

Lets remind ourselves that the root cause of Cross-Site Scripting is missing  encoding of user inputs. Having the right encoding at the source is obviously the true antidote to this class of vulnerabilities. Luckily, the template engine available in .NET is doing some encoding by default.

Here is a list of vulnerable templates using the Razor template engine. The examples assumes that the values displayed are controlled by the user.

  • Unsafe HTML
Hello @Html.Raw(ViewBag.Name)

If direct binding was used (@ViewBag.Name), it would be encoded properly the value for the HTML context. In the HTML context, special characters are replaced by XML entities such as < , > and ".

  • Unsafe Html.Raw in attributes
<a href="/ViewDetails?name=@Html.Raw(ViewBag.Name)">View Details</a>

In this unsafe example, the developer might have disabled the encoding because he realizes that the default encoding to HTML entities is not appropriate for URLs. Special characters are replaced by entities (ie " becomes &quote;). A context specific function should have been used. Server.UrlEncode() can be used to encode safely a value in an URL.

  • Unsafe action link
@Html.ActionLink("Open page", null, null, null, new { href = @ViewBag.Url })

With the first ActionLink, an attacker could use the URL « javascript:[...] » to trigger malicious JavaScript. A validation of the URL is needed in the controller.

@Html.ActionLink("Back to previous page", null, null, null, new { href = Request.UrlReferrer })

The second ActionLink example could lead to an Open Redirect. It does not lead to arbitrary JavaScript execution but it could be used as an effective means for stealing credentials or phishing attacks.

  • Unsafe « unquoted » attribute

Attributes in Razor template can become vulnerable to XSS in two scenarios: when Html.Raw is used (see Unsafe Html.Raw in attributes) or when an attribute is not placed in quotes. Razor does not enforce the use of single or double quotes.

<img src=logo.png alt=@(ViewBag.ImageId)>

Here a malicious user controlling the ImageId variable could add a JavaScript event such as onload or onerror. The following snippet illustrate a basic injection.

<img src=logo.png alt=''onload='alert(1)'>
  • Another example with unquote attribute that could lead to DOM clobbering
<form class=@(ViewBag.FormClass) action="SubmitMe">
</form>

In this particular case, a form with the injected properties « name » and « id » can lead to shadow JavaScript global variables that are injected later in the DOM. It is a very capricious attack vector that works for very specific property names. If you want to know more about it, you can read Gareth Heyes article on DOM clobbering.

  • Script context
<script>
api.SearchUser('@(ViewBag.FirstName)','@(ViewBag.FirstName)');
</script>

Finally, the script context is slightly more at risk because the value are escaped to HTML entities by default. In the example above, it is possible to inject JavaScript because HTML special characters are escaped but not blackslash (\).

<script>
api.SearchUser('Dummy\',');prompt(1234)//');
</script>

In the previous example, the blackslash escape the terminating single quote. This cause the string to actually close on the following single quote. The second parameter can then be use by the attacker introduce malicious Javascript.

  • Client-side template context

Most special characters are escaped in the HTML context. However, some Javascript libraries loaded on your web page may load dynamic expression from the DOM. It is the case of AngularJS. AngularJS will evaluate expressions between brackets ({{ ... }}) to its own scripting language. AngularJS expression are powerfull enough to lauch arbitrary JavaScript.

The following page might look safe.

<script src="@Url.Content("~/Scripts/angular-1.6.6.min.js")" type="text/javascript"></script>[...]
<h1>Content:</h1>
@Model.Content

It is possible to execute a malicious JavaScript like this:

{{constructor.constructor('alert(1)')()}}

 

To summarize the correct guidelines, we have create a cheat sheet that include code examples  for the different contexts. It is intend to be a quick reminder for developers or security auditors doing code review. Feel free to share this cheat sheet to developers of your organisation.

 

Request Validation

RequestValidation error message (input blocked)

 

Request Validation is a built-in filter to ASP.net. It is an additional layer of protection that is intended to block malicious requests. It will stop suspicious request if the parameters contains any HTML tag.

The Request Validation module is a feature that is integrated to ASP.net framework. It is decoupled from the View ASP forms or Razor Templates. It can be view as a Web Application Firewall for XSS specifically.

 

Bypasses

Any transformation between the moment the request is received and the construction of the final HTML view can lead to filter bypass. If an HTTP parameter is URL decoded two times, it is enough to bypass the filter.

One of the common transformation is SQL server character conversion to ASCII. It can occurs if the column data type is not unicode (VARCHAR vs NVARCHAR). SQL Server will convert the Unicode character FF1C to 003C. This is sufficient to bypass RequestValidation to create a Stored XSS.

Character Character After storage
U+FF1C (%EF%BC%9C) U+003C (%3C)
U+FF1E (%EF%BC%9E) U+003E (%3E)

A malicious payload using this bypass would look like this:

Name=XSS_HERE_%EF%BC%9Cimg%20src%3Dxxx%20onerror%3Dalert(1)%EF%BC%9E

Once the value would be output, it will be display as < (u+003C) and > (u+003E).

XSS_HERE_<img src=xxx onerror=alert(1)>

Nonetheless, it is still recommended to keep RequestValidation as a extra safe guard. As the official documentation stated, it is not a replacement to validation and proper encoding.

 

Client-side filters

Modern browsers also provide an additional layer of protection. Chrome, Internet Explorer and Edge have a filter mechanism that can detect some reflected XSS. The browsers will find some patterns were HTML tags are passed in the URL or POST parameters and are reflected in the page.

Browser XSS Filter
Mozilla Firefox None
Google Chrome Yes
Internet Explorer / Edge Yes

The filter can also be forced with the header X-XSS-Protection: 1. This has limited benefits because the filter is already enabled by default in Chrome, Internet Explorer and Edge. However, for some hosts (like localhost), IE/Edge will disable its filter by default.

 

Additional configurations

  • X-XSS-Protection: 1; mode=block : It is possible to block the loading of the page if a malicious pattern is detected. It is intended to avoid unwanted scripts being disabled.
  • X-XSS-Protection: 1; report=http://myhost.com/report : With this directive the browser will report blocked parameters to the URL specified in the header.

Even though  the filters have been proved to be effective, there is no commitment from the Chrome and Edge teams to provide a complete coverage.

 

Bypasses

Browser filters do not cover stored XSS and some DOM XSS. They also have some known bypasses. Usually, a transformation will lead to filter bypass. In the following example, the value is properly HTML encoded. However, JavaScript will read the attribute and print it. It will trigger an XSS because once the attribute is read the entities are decoded.

http://website.com/example?userId=%3Cimg%20src=xx%20onerror=alert(1)%3E


<form action="">
<input type="hidden" id="userId" name="userId" value="&lt;img src=xx onerror=alert(1)&gt;" >
</form>
[...]
<div id="preview"></div>
[...]
<script> document.getElementById("preview").innerHTML = "Hello "+document.getElementById("userId").value; </script> 

 

Conclusion

This article should cover the key elements when it comes to safe HTML encoding and XSS prevention. You should now be aware of some of the limitations of each components. It should also stand out that security is not a silver bullet. Relying on a single protection will increase the probability of malicious payload passing through.

As mention previously, feel free to share this cheat sheet to developers of your organisation. The cheat sheet will evolve in the next month to include additional languages and frameworks. The project is open for contribution and reuse.

 

References

Détection et réponse gérées et étendues GoSecure TitanMC (MXDR)

Détection et réponse gérées et étendues GoSecure TitanMC (MXDR) Fondation

Gestion des vulnérabilités en tant que service GoSecure TitanMC (VMaaS)

Surveillance des événements liés aux informations de sécurité gérée GoSecure TitanMC (SIEM gérée)

Défense du périmètre gérée GoSecure TitanMC (pare-feu)

Détection et réponse des boîtes de messagerie GoSecure TitanMC (IDR)

Passerelle de messagerie sécurisée GoSecure TitanMC (SEG)

Modélisateur de menaces GoSecure TitanMC

Identity GoSecure TitanMC

Plateforme GoSecure TitanMC

Services de sécurité professionnels de GoSecure

Services de réponse aux incidents

Évaluation de la maturité de la sécurité

Services de confidentialité

Services PCI DSS

Services de piratage éthique

Opérations de sécurité

MicrosoftLogo

GoSecure MXDR pour Microsoft

Visibilité et réponse complètes au sein de votre environnement de sécurité Microsoft

CAS D'UTILISATION

Cyberrisques

Mesures de sécurité basées sur les risques

Sociétés de financement par capitaux propres

Prendre des décisions éclairées

Sécurité des données sensibles

Protéger les informations sensibles

Conformité en matière de cybersécurité

Respecter les obligations réglementaires

Cyberassurance

Une stratégie précieuse de gestion des risques

Rançongiciels

Combattre les rançongiciels grâce à une sécurité innovante

Attaques de type « zero-day »

Arrêter les exploits de type « zero-day » grâce à une protection avancée

Consolider, évoluer et prospérer

Prenez de l'avance et gagnez la course avec la Plateforme GoSecure TitanMC.

24/7 MXDR

Détection et réponse sur les terminaux GoSecure TitanMC (EDR)

Antivirus de nouvelle génération GoSecure TitanMC (NGAV)

Surveillance des événements liés aux informations de sécurité GoSecure TitanMC (SIEM)

Détection et réponse des boîtes de messagerie GoSecure TitanMC (IDR)

Intelligence GoSecure TitanMC

Notre SOC

Défense proactive, 24h/24, 7j/7

À PROPOS DE GOSECURE

GoSecure est un leader et un innovateur reconnu en matière de cybersécurité, pionnier de l'intégration de la détection des menaces au niveau des terminaux, du réseau et des courriels en un seul service de détection et réponse gérées et étendues (MXDR). Depuis plus de 20 ans, GoSecure aide ses clients à mieux comprendre leurs failles en matière de sécurité et à améliorer leurs risques organisationnels ainsi que leur maturité en matière de sécurité grâce aux solutions MXDR et aux services professionnels fournis par l'une des équipes les plus fiables et les plus compétentes de l'industrie.

CALENDRIER D’ÉVÉNEMENTS

DERNIER COMMUNIQUÉ DE PRESSE

BLOGUE GOSECURE

AVIS DE SÉCURITÉ

Urgences 24 sur 7 – (888) 287-5858