“Bolt-On” CSRF Protection in Intranet Web API Windows Authentication Scenarios

Web API is a powerful tool for constructing web services, but also for separating concerns of a web application. However, like any web application, security concerns must be addressed. One of the most common security concerns with authenticated operations is cross-site request forgery. In a traditional ASP.NET MVC application, we can use the built-in AntiForgeryToken mechanism to place a unique token within each page served to the client, and require that token be included in any requests back to the server. Since an attacker cannot access the contents of the actual served page, they are unable to acquire the token; and since the token is not a cookie or credential, the browser will not send it automatically. Thus, an attacking page cannot craft an effective CSRF attack.

When moving into the Web API world, things are a little more muddy. The general tack has been to take a different angle on authentication and authorization all together. For example, the use of certificates to sign each request, bearer tokens, oAuth, or similar approaches. However, for purely intranet applications, we may still wish to use Windows authentication. This means the end-user of a website which calls our API will automatically do so with the user’s windows credential. (It is also possible for server-side applications to use impersonation to call the API with a particular Windows service account, however, this is not subject to CSRF vulnerability).

There are also ways to make a joint MVC/Web API application use the MVC anti-forgery tokens, which is really neat, but only works if the API and application are one cohesive web application solution, as otherwise the Web API’s instance of ASP.NET would differ from the MVC instance of ASP.NET, and they would not share the set of valid anti-forgery tokens. It also doesn’t work if “plain” HTML/JS is being used to access the API.

However, by using Windows authentication, we open our API up to CSRF attackers. An intranet user may be using a web application which uses our API (and thus, carries their credential), while at the same time they are browsing evilattacksites.com which can construct a form with the intranet URL and post it to the API’s intranet address. This post will carry the user’s credentials with it, and execute a successful attack.

You might note that the API is on a intranet site and the attacker is (probably) external, so CORS might be suggested as an answer. However, CORS only controls what data can be read, it does not protect against CSRF submissions.

We want Web API CSRF protection that:

  • Works with any client (doesn’t require pages generated by MVC)
  • Works with Windows authentication/intranet
  • Is easy to “bolt-on” to existing Web API services AND clients

Closing the CSRF Vulnerability

The solution we will use is to provide a per-IP CSRF token that must be attached to the HTTP header and is validated on all POST/PUT/DELETE requests.

The technique here is to construct a message handler which will process all Web API requests before they go to the controller. It will validate the presence of a CSRF token when needed, and produce it when requested. Thus, there will be no changes to the controllers! The only server-side application change (besides importing the message handler), is to add it in the WebApiConfig Register method.

config.MessageHandlers.Add(new Infrastructure.CSRFMessageHandler());

On the client side, none of the individual requests to the API need to be altered. An initial login call (handled by the CSRFMessageHandler on the server) acquires the CSRF token and places it into the headers for all subsequent ajax calls. There will be no other changes needed to the client. However, clients which consume multiple Web API services secured in this way will have a more complex setup procedure. 🙂

$(function () {
   $.ajax("../api/login")
      .done(function (data) { $.ajaxSetup({ headers: 
         { "X-CSRF-Key": data } }) })
      .fail(function () { /* DO SOMETHING */ });
});

With no further changes, the API is now secure, and the clients receive and use the CSRF token to gain access. This protection can easily be “bolted on” to existing APIs and clients.

Implementation of CSRFMessageHandler

The real magic of this technique is in CSRFMessageHandler. This handler intercepts each call to the Web API before it is sent to the controller. There are two parts: the CSRF token verification, and the token generation.

First, the overall class structure of the handler. We prepare a RNGCryptoServiceProvider for generating the token, and extract the request context so we have access to the ASP.NET application state object, where the CSRF tokens will be stored (you could also store them in a database, or other repository).

public class CSRFMessageHandler : DelegatingHandler
{
   private static readonly RNGCryptoServiceProvider rng = 
      new RNGCryptoServiceProvider();
   public const string CSRF_HEADER_NAME = "X-CSRF-Key";      

   protected override async Task<HttpResponseMessage> SendAsync(
      HttpRequestMessage request, CancellationToken cancellationToken)
   {            
      var method = request.Method.Method.Trim().ToUpper();

      // Extract the context from the request property
      // so that application "state" can be accessed
      var context = ((HttpContextBase)request.
         Properties["MS_HttpContext"]);

      // PART ONE: On "login" request, create token.  
      // Put this here so no need to modify controller.
      ... see below
      // PART TWO: For update methods, enforce the CSRF key
      ... see below

      return await base.SendAsync(request, cancellationToken);
   }
}

When the client sends a “login” request (any request ending in /login), it will be intercepted by the handler and a CSRF token will be created and returned. If desired, you could check the dictionary to see if the client already has a key and reuse it. You could send back the username along with the key. You could set an expiration time for the key and make a process to remove old (expired) keys. Some additional improvement is definitely possible.

if (method == "GET" && 
   request.RequestUri.AbsolutePath.ToUpper().EndsWith("/LOGIN"))
{
   var keys = context.Application[CSRF_HEADER_NAME] as 
      IDictionary<string, string>;
   if (keys == null)
   {
      keys = new Dictionary<string, string>();
      context.Application[CSRF_HEADER_NAME] = keys;
   }

   byte[] bkey = new byte[16];
   rng.GetBytes(bkey);
   var key = Convert.ToBase64String(bkey); 
   keys[context.Request.UserHostAddress] = key;
   return new HttpResponseMessage(HttpStatusCode.OK) 
   { 
      Content = new StringContent(key) 
   };
}

For all modification requests (POST, PUT, DELETE), the handler will validate that the appropriate key is included in the headers.

if (method == "POST" || method == "PUT" || method == "DELETE")
{
   HttpResponseMessage response = request.CreateErrorResponse(
      HttpStatusCode.Forbidden,
      "POST/PUT/DELETE require valid and matching anti-CSRF key, use Login method");

   string key = null;
                
   if (request.Headers.Contains(CSRF_HEADER_NAME))
      key = request.Headers.GetValues(CSRF_HEADER_NAME).Single();

   var keys = context.Application[CSRF_HEADER_NAME] as 
      IDictionary<string, string>;
   string ipaddr = context.Request.UserHostAddress;
   
   // match to the key for user's IP address
   if (keys == null ||
      !keys.ContainsKey(ipaddr) ||
      keys[ipaddr] != key) throw new HttpResponseException(response);
}

“Class”-like Inheritance, Overriding, and Superclass Calls in JavaScript

JavaScript is a prototype-based language with objects, rather than classes, as its fundamental construct. However, the use of functions to approximate classes (complete with the “new” keyword) is very common. Although we’re often told that JavaScript supports inheritance, it’s not entirely obvious how the class-like inheritance works in a prototype-based language such as JavaScript. Adding to the confusion is various syntax approaches that may be used to devise objects and “classes”.

As an aside, the techniques shown in this post require ES5 support, which, for example, excludes IE 8 and below. There are fairly simple shims that can be used to enable support in older browsers.

We’ll first consider a “naive” approach to defining a class in JavaScript, then discuss why this approach isn’t suitable for an inheritance scenario.

function BaseClass(initialValue) {
  this.value = initialValue;
  this.compute = function() { return this.value + 1; };
};

This class seems to work fine:

var instance = new BaseClass(3);
console.log(instance.compute()); // outputs 4

However, this approach is not suitable for inheritance. The function “compute” (and any other functions defined in this way) will be defined not on the “class” (prototype) but on the object itself. When overridden, there will be no reasonable way to access the base function, because the override will actually replace the original function on that object. Thus, functions should be defined on the prototype, while fields are defined on the object itself. If you define a field on the prototype, it is like a static member in C#.

function BaseClass(initialValue) {
  this.value = initialValue;
};
BaseClass.prototype.compute = function() { return this.value + 1; };

This produces the same result as before, but now the function is defined on the prototype instead of the object, so it can be referenced by derived classes.

Now imagine we want to construct a derived class. There are two important considerations: ensuring that the super-constructor is called correctly, and ensuring that “instanceof” continues to give the correct result. There is no “base” or “super” keyword in JavaScript, so you must use the actual name of the base class whenever you want to refer to it.

function DerivedClass(initialValue, secondValue) {
  BaseClass.call(this, initialValue); // *** Call super-constructor
  this.anotherValue = secondValue; // Additional field
};
// *** Establish prototype relationship
DerivedClass.prototype = Object.create(BaseClass.prototype); 

// Additional function
DerivedClass.prototype.anotherCompute = 
   function() { return this.compute() + this.anotherValue; }; 

Now let’s look at the things we can do with an instance of the derived class. They should all work as expected.

var instance2 = new DerivedClass(4, 6);
// base method with base fields: outputs 5 (4+1)
console.log(instance2.compute()); 

// derived method with base method and derived field: 
// outputs 11 ((4+1)+6)
console.log(instance2.anotherCompute()); 

// outputs true
console.log(instance2 instanceof DerivedClass); 

// ALSO outputs true
console.log(instance2 instanceof BaseClass); 

Now imagine we want to create a derived class that overrides some behavior of the base class. First, we will create a class inheriting from the previous derived class, and override the compute method.

function ThirdClass(initialValue, secondValue) {
  // In this case, the "base" class 
  // of this class is called "DerivedClass"
  DerivedClass.call(this, initialValue, secondValue); 

  // no new member fields
};
ThirdClass.prototype = Object.create(DerivedClass.prototype); 

// override base function compute
ThirdClass.prototype.compute = function() { return 100; }; 

Let’s see this overridden function in action. The override also impacts, for example, the “anotherCompute” function since it calls compute. The overriding works exactly as you would expect as in, say, C#.

var instance3 = new ThirdClass(4, 6);
// overridden method always outputs 100
console.log(instance3.compute()); 

// derived method with OVERRIDDEN method (inside) and derived field: 
// outputs 106 (100+6)
console.log(instance3.anotherCompute()); 

// confirm that the compute has only been overridden 
// for instances of ThirdClass: 
// outputs 5, as before
console.log(instance2.compute()); 

One final task remains: can we override a function, and then still make a call to the base class version of that function? In this case, we’ll replace the definition of compute in the third class with one that overrides compute while also making a class to the base class definition of compute. This is where the technique for function definition (defining on the prototype vs. defining on the object) becomes critical. Since the functions are actually defined on the prototypes, we can call back to the base class prototype for that version of the function. Remember that “ThirdClass” derives from “DerivedClass”

// override base function compute, but still use it in this function
ThirdClass.prototype.compute = function() { 
  return DerivedClass.prototype.compute.call(this) * 5; 
}; 

Now we’ll retry the two instance3 calls from earlier:

// overridden method calls base implementation of compute, 
// which returns 5, and multiplies it by 5. output: 25
console.log(instance3.compute()); 

// derived method with overridden method
// (inside, which calls base implementation) 
// and derived field: outputs 31 ((5*5)+6)
console.log(instance3.anotherCompute()); 

We now have a reliable technique for constructing “class”es in JavaScript which fully support inheritance, overriding, and superclass calls in the way conventional from class-based object-oriented languages.

Remember, though, that this is “writing C#/Java in JavaScript” and should be used sparingly. Also, some authors believe implementation inheritance is usually bad even in languages which support it as a primary form of reuse.

Quickly Tell When You’re Connected to Production in SQL Management Studio

This is one of those things that “everybody knows” but I don’t find out about until years later (like pushing Windows-L to lock the workstation).

If you have access to various environments in SQL (dev, multiple test/QA machines, and production) sometimes there can be fear: am I connected to the correct server? I often stop and re-read the connection information to be sure I’m on the right server before I execute a command that could be particularly troublesome. I intentionally minimize my permissions in production to help reduce this, but there are still some permissions that exist; and some folks have more production permissions because they change it frequently.

So, here’s an easy way to help reduce anxiety. In SQL Management Studio 2008 and above, you can set custom status bar colors depending on which server you are connected to. Very easy.

When establishing the connection, simply press the “Options” button on the bottom right:
sql1

Then, you can check the box to show a custom color. SQL Management studio will save this value, and for all new query windows that are opened, will highlight the bottom status bar if that server is connected. An easy way to “warn” yourself if connected to a shared environment, and a quick confidence to know when you’re connected to a local dev environment only.

sql2

Posted in SQL