Monday 13 December 2010

Configuration Transforms in ASP.Net Web Deployment Projects

In a recent web application project, we have many different environments where we need to regularly deploy our application such as 'development', 'testing', 'staging', and 'live'. For most, the standard publishing in Visual Studio 2010 works wonders, and I have been giddily using new build configurations and publishing profiles with fantastic results. In short, I just choose the build configuration to match the environment, choose the corresponding publishing profile, and hit go... (it used to take me ages to copy files across, change configuration settings etc...)

One problem I had with this was for the live deployment. Although the configuration transforms were working great for publishing, for the live environment we also wanted to apply the minify tasks to the CSS and JavaScript files (See my other post on post build tasks and minification).

Web Deployment Projects
Currently, web deployment projects don't apply the configuration transforms, so I had to find another way to apply this. Since I already had post build tasks in place for the minification, I figured this was the way to go to apply the transformations. After finding this question I was almost there.

Using the above post, I was able to identify the task used to transform the configuration files in the V10.0 publishing assembly. Unfortunately once the task has run it leaves the files locked by the process so in addition I had to add a couple of additional tasks to copy the files to a temporary location first, and copy back across to the project folder when done. Once this was complete I setup a task to delete the redundant files for other build configurations and remove the temporary file if possible (the temp file appeared to still be locked by the process so may not delete in some cases. However, this directory will be overwritten by the standard process the next time you build anyway).

The build task configuration is below. If you right click on the web deployment project and select 'Open Project File' you should be able to paste this in at the bottom (I have excluded the Minify task for brevity).

<UsingTask TaskName="TransformXml" AssemblyFile="$(MSBuildExtensionsPath)\Microsoft\VisualStudio\v10.0\Web\Microsoft.Web.Publishing.Tasks.dll" />

<Target Name="AfterBuild">
<!-- Copy the config transform file to a temp directory (to stop it being locked by the process) -->
<Copy SourceFiles="$(Configuration)\web.$(Configuration).config" DestinationFolder="TempBuildDir\" />
<!-- Delete the config files from the deploy folder (to be replaced by the transformed files) -->
<ItemGroup><ConfigFiles Include="$(Configuration)\\**\*.*.config" /></ItemGroup>
<Delete Files="@(ConfigFiles)" />
<!-- Transform the copied files and write to the deploy folder -->
<TransformXml Source="$(SourceWebPhysicalPath)\Web.Config" Transform="TempBuildDir\Web.$(Configuration).config" Destination="$(Configuration)\Web.config" StackTrace="true" />
<!--Then remove the temp files folder (locked by the transform process...)-->
<RemoveDir Directories="TempBuildDir\" ContinueOnError="true" />
</Target>

Conclusion
This enables the web deployment project to build the website with the correct configuration AND minified JavaScript and CSS files. I can then build the package and distribute via the web deploy tool in IIS7.

Monday 6 December 2010

Penetration Test Checklist

During a recent web application release, we subjected our new site to penetration testing. Some of the things they came back with were the standard school boy errors (like failing to encrypt the cookies) but some were more interesting and that I haven't come across before. I will attempt to outline some below, more as a reference for my future self but if its any use for someone else then great.

Encrypting cookies
In the past, this has stung me because you can only include it when you have a certificate installed for the website (which meant I could only make the setting change after the certificate was installed and application deployed).

The easiest way to sort this is to include it in the configuration file, and with the new configuration transforms its easier than ever.

<authentication mode="Forms" xdt:Transform="Replace">
<forms loginUrl="~/Login.aspx"
defaultUrl="~/Default.aspx"
protection="All"
name="MyWebApp"
requireSSL="true" />
</authentication>

Clickjacking Mitigation
To help prevent clickjacking on pages that don't need to be framed, the new X-FRAME-OPTIONS header can be included to tell browsers not to allow framing. Again the easiest way to do this is through the web configuration file (this only applies to IIS7 within the system.webServer node)

<httpProtocol>
<customHeaders>>
<clear />
<add name="X-FRAME-OPTIONS" value="DENY" />
</customHeaders>
</httpProtocol>

Details of the different options to use can be seen in EricLaws blog combatting clickjacking with X-Frame-Options.

Server Http Header
For some reason, IIS loves to tell the world about itself for every page request. Although this doesn't necessarily pose a threat, it does make it easier for hackers to see which server you are using and narrow down the exploits to try against your website.

Various approaches can be taken to remove this, there is a free tool available from Microsoft called UrlScan which can block specific Http requests and works on IIS 5.1 and above. On IIS7 you can create a custom module (or build into your application) which replaces the Server header with your own. You can then include the custom module as a reference within your application and load it using the configuration file, or compile to an assembly in the GAC and apply to all applications on your server.

Remove 'X-AspNet-Version header'
ASP.Net by default serves up the http header X-AspNet-Version with the version information. Again although this doesn't pose a direct risk, it does give more information to potential hackers to let them focus on particular exploits.

To remove this header, just change the configuration file as follows:

<system.web>
<httpRuntime enableVersionHeader="false" />
</system.web>

This can be added to the configuration transform as before so it only applies to your live deployment, though personally I don't see a problem with just removing it for all environments.

Remove 'X-Powered-By'
Similar to the X-AspNet-Version header, ASP.Net sometimes (depending on the web server) serves an X-Powered-By http header which advertises that the application is ASP.Net (sometimes even if it isn't). To remove this in IIS6 there's a great post showing the steps required. For IIS7 you can use the configuration file (or do it manually following the steps on the link above). In the <system.webServer> node add the following:

<httpProtocol>
<customHeaders>
<clear />
<remove name="X-Powered-By" />
</customHeaders>
</httpProtocol>

X-AspNetMvc-Version
For ASP.Net MVC applications, an additional 'X-AspNetMvc-Version' header is included. This can be removed by adding the following code to the Application_Start event in the Global.asax file:

MvcHandler.DisableMvcResponseHeader = true;

HTTP OPTIONS
The OPTIONS method allows users to tell what sort of http options (GET/POST/etc...) are available without actually executing the action. Again this (some say) gives potential hackers more information about your application that can be exploited. To turn off the OPTIONS verb, you can deny access to unauthorised users with the <authorization> node.

<authorization>
<deny users="?" />
<deny verbs="OPTIONS" users="*" />
</authorization>

Conclusion
So that's it, of course your website will have to be properly secured using the usual development and configuration steps. These additions won't secure your website as such, but they will help to hide the extra information that can be used against you and your application.