…and why you should report it (maybe).

This post is regarding the .NET Request Validation vulnerability, as described here. Note that this is nothing new, but I am still finding the issue prevalent on .NET sites in 2017.

Request Validation is an ASP.NET input filter.

This is designed to protect applications against XSS, even though Microsoft themselves state that it is not secure:

Even if you’re using request validation, you should HTML-encode text that you get from users before you display it on a page.

To me, that seems a bit mad. If you are providing users of your framework with functionality that mitigates XSS, why do users then have to do the one thing that mitigates XSS themselves?

Microsoft should have ensured that all .NET controls properly output things HTML encoded. For example, unless the developer manually output encodes the data in the following example then XSS will be introduced.

<asp:Repeater ID="Repeater2" runat="server">
  <ItemTemplate>
    <%# Eval("YourField") %>
  </ItemTemplate>
</asp:Repeater>

The <%: syntax introduced in .NET 4 was a good move for automatic HTML encoding, although it should have existed from the start.

Now to summarise, normally ASP.NET Request Validation blocks any HTTP request that appears to contain tags. e.g.

example.com/?foo=<b> would result in A potentially dangerous Request.QueryString value was detected from the client error, presented on a nice Yellow Screen of Death.

This is to prevent a user from inserting a <script> tag into user input, or from trying some other form such as <svg onload="alert(1)" />.

However, the flaw in this is that <%tag is allowed. This is a quirky tag that only works in Internet Explorer 9. But ironically not quirks mode, it requires IE9 standards mode so the top of the page must contain this Edit: It works in either mode, however if the page is in quirks mode then it requires user interaction (like mouseover). Example, the existing page can seen to be in quirks mode as it contains the following type definition and meta tag (although in tests only the meta tag seems to be required):

<!doctype html>
<meta http-equiv="X-UA-Compatible" content="IE=Edge">

I’ve setup an example here that you can try in IE9. The code is as follows:

<!doctype html>
<html>
<head>
	<meta http-equiv="X-UA-Compatible" content="IE=Edge">
</head>
<body>

	<%tag onmouseover="alert('markitzeroday.com')">Move mouse here

</body>
</html>

Loading your target page in Internet Explorer 9 and then viewing developer tools will show you whether the page is rendered in quirks mode.

Moving the mouse over the text gives our favourite notification from a computer ever - that which proves JavaScript execution has taken place:

XSS Proof

Edit: Actually this does work in quirks mode too using a CSS vector and no document type declaration:

<html>
<head>
</head>
<body>

        <%tag style="xss:expression(alert('markitzeroday.com'))">And you don't even have to mouseover

</body>
</html>

Example Warning: This is a trap, and you may need to hold escape to well… escape.

Now, you should report this in your pentest or bug bounty reports if you can prove JavaScript execution in IE9, either stored or reflected. Unfortunately it is not enough to bypass Request Validation in itself as XSS is an output vulnerability, not an input one.

Note that it is important that this is reported, even though it affects Internet Explorer 9 only. The reasons are as follows:

  • Some organisations are “stuck” on old versions of Internet Explorer for compatibility reasons. Their IT department will not upgrade the browsers network wide as a piece of software bought in 2011 for £150,000 will not run on anything else.
  • By getting XSS with one browser version, you are proving that adequate output encoding is not in place. This shows the application is vulnerable should it also use data from other sources. e.g. User input from a database shared with a non ASP.NET app, or an app that is written properly as not to rely on ASP.NET Request Validation.
    • Granted you can only test inputs from your “in-scope” applications and prove that those inputs have a vulnerable sink when output elsewhere, although chances are that if one part of the application is vulnerable then other parts will be and you can alert your client to this possibility quite literally.

Note also that Request Validation inhibits functionality. Much like my post on functional flaws vs security flaws, preventing a user from entering certain characters and then resolving this by issuing an HTTP 500 response results in a broken app. If such character sequences are not allowed, you should alert the user in a friendly way and give them chance to fix it first, even if this is only client-side validation. Also any automated processes that may include <stuff that it POSTs or GETs to your application may unexpectedly fail.

The thing that Microsoft got wrong with Request Validation is that XSS it an output problem, not an input problem. The Microsoft article linked above is still confused about this:

If you disable request validation, you must check the user input yourself for dangerous HTML or JavaScript.

Of course, if you want a highly secure site as your risk appetite is low, then do validate user input. Don’t let non alphanumeric characters be entered if they are not needed. However, the primary mitigation for XSS is output encoding. This is the act of changing characters like < to &lt;. Then it doesn’t matter if this is output to your page as the browser won’t execute it and therefore no XSS.

So as a pentester, report it if IE9 shows the alert, even if IE9 should be killed with fire. As a developer, turn Request Validation off and develop your application to HTML encode everywhere (don’t output into JavaScript directly - just don’t). If you need “extra” security, prevent non alphanumerics from being inserted into fields yourself through server-side validation.