A Safer Site

Posted on June 15, 2015 in umbraco and edited on June 18, 2015

If you were at CodeGarden 15 and have attended Chris Gaskell Securing your Umbraco session, you might have found yourself suddenly wondering whether your nice Umbraco site was safe at all. I know I did.

So, back home, I fired a tool he mentionned, ASafaWeb, against this site and got the result below. Oh my—orange and red—reasons to be scared!

OK, so it is time we go fixing.

Headers

Excessive headers and Clickjacking all come down to http headers. It looks like I am returning the Server and X-AspNetMvc-Version headers, and I am missing the X-Frame-Options header. Should be easy to fix, right? Well, considering the number of blog posts listing near-voodoo magic solutions, it is not.

I initially decided that NWebsec looked fine. Installing this tool (as a NuGet package) in the web application modifies the web.config file, registers a new module and adds an empty configuration section, where one can copy some settings from the Getting Started section of the documentation. Rebuild, reload, and headers look perfect.

Yet ASafaWeb still complains, because our error page still has the Serverheader. Oh, and ASafaWeb triggers the error by reaching the /trace.axd page, because trace is disabled on the live server. We have two problems here:

Now that we have StripHeaders installed, maybe we do not need NWebsec anymore. But that would mean figuring out the anti-clickjack by ourselves... we will be running both.

Errors

Custom errors is easy to check: just hit eg www.zpqrtbnk.net/< (note the "lower than" character) and it triggers a "potentially dangerous request" exception, which on the live site translates into a YSOD explaining how to manage custom errors in web.config. Not pretty.

And strange. I do have a module handling the HttpApplication.Event event, logging the exception to disk, and writing the content of a nice html file back to the client. How come it does not show?

Well, not all errors are "500" errors. The "potentially dangerous request" mentioned above is a "400" error. So I have changed my condition to output the html file if the status is greater than, or equal to 400, but not equal to 404.

And then, if you really really want to make sure that neither ASP.NET or IIS will try to be clever and manage the error by themselves, you want to end your handler with:

context.Response.TrySkipIisCustomErrors = true;
context.Server.ClearError();
context.ApplicationInstance.CompleteRequest();

And now we have a nice Umbraco-managed 404 page, a nice 500 page that triggers on real errors, and trace.axd just causes a 404. Are there other ASP.NET pages that cause errors instead of 404? Pretty sure. Why do static page 404 (eg a JPG) display a blank page? No idea. But I am running out of time: will deal with it later.

Safer it is

Fire ASafaWeb again, and sure enough, it's much happier.

So, I am feeling better. However, call me paranoid, the idea of having the Umbraco back-end publicly accessible annoys me a lot. I mean, we try to hide our server version, our ASP.NET version, but we still reveal that we run Umbraco by displaying the back-end login screen?

This website runs a custom module that blocks all accesses to the /umbraco path by redirecting to the home page, unless you first hit a url looking like /76d161694013457bbf442075573963fd. Doing this creates a session cookie and unlocks the back-end. Granted, it's probably security through obscurity, but I feel better knowing that, should a security issue in the back-end be published tomorrow, script kiddies would have a hard time exploiting it on my site.

How do you secure your website?

Update 06/18

When configuring NWebsec, make sure the X-Frame-Option policy is set to SameOrigin and not Deny, as that breaks parts of Umbraco's backend.

There used to be Disqus-powered comments here. They got very little engagement, and I am not a big fan of Disqus. So, comments are gone. If you want to discuss this article, your best bet is to ping me on Mastodon.