I have compiled a check list of tips and techniques that I have built up in the years of development in .Net – So I’m here to share them with you all – so that you can also develop more securely in your own projects.
1. Configuration – SSL and services
Once your website is live to the public, it’s a good idea if you have control of the server to uninstall or disable services that aren’t required. Anything other than HTTP/HTTPS left open to the public is a risk. Try to enforce SSL for parts of your website that you wish to encrypt the data for. The SSL connection will ensure the data between the webserver and the client browser is encrypted end to end. Normal situations for this include payment processing etc.
2. Deployment – Release Build
Once you have done your testing – make sure you only deploy a “release” build of your website. It will remove all the debug code that is automatically injected when you are normally testing the website. It means if anything does happen/crash, there will be less information displayed to the user on-screen.
3. Deployment – Exception Handling
Inside the Global.asax file that is generated with all website projects in .Net, put code in the Application_Error function to capture any exception that may occur that isn’t handled properly in the website code. There are always scenarios that we can’t/don’t test, and slip through the gaps. Get the code to log the issues internally, and display a User-Friendly error page to the user. Do not reveal any error specific information in the Error Page.
4. Database – Queries
When accessing data to and from the database, make sure you use Stored Procedures instead of generating SQL queries dynamically. Because the query is outside the code base – there is no potential for the query to be altered/re-written. It does happen in attacks through a series of different attacks like Cross-Site scripting (XSS) and SQL Injection. If there is potential for the query to change, you have to assume that it might happen.
5. Database – Sanitization
When storing any strings/data in the database – you should sanitize your data by using the built in Server.HTMLEncode/Server.HTMLDecode functions to store the data safely. It will remove any script injections from being readable.
6. Field Input – Sanitization
All fields on a screen can be changed, even if they are labels or disabled textboxes through scripts/man-in-the-middle attacks (MITM). All data inputted must be validated correctly for format, and for XSS/Sql Injection input. Microsoft provides a library that can help deal with this – called Microsoft Anti-XSS (http://msdn.microsoft.com/en-us/library/aa973813.aspx). Funnily enough it’s been around since 2005/2006 and still hasn’t been incorporated into Visual Studio yet.
7. Password requirements
Ensuring users make it more difficult for anyone to guess their password; you need to enforce decent rules for a valid password. There needs to be a mix of upper/lowercase, symbols and numbers with at least 1 or 2 of each and a minimum length of 8-16 characters. The longer the harder it is to guess.
8. Login functionality
They should never reveal what exactly is wrong with the credentials – leave room for ambiguity. “Wrong Login or Password” is more secure than “Wrong Password for this Login”. Similar principle applies to Forgotten Password pages – never inform the user that the email/user specified was found – but more like “If the user/email exists, then a password will be sent to the user.”
9. Brute Force attempts
A method to prevent this from happening/affecting your website – Every failed attempt to login is counted by IP Address, once this hits a set limit (I used 3 attempts), does a lockout for the attack for 5 minutes. Each attempt returns the same error message “Invalid Login or Password” – even once the lockout has occurred. The user has no idea that the system isn’t even checking the login or password anymore since you have missed it too many times. Every sequential attempt during the lockout period restarts the lockout delay. This method prevents tools that are attempting brute-force attempts, as they keep trying different combinations and read the output on the page to understand it has a wrong Login/password combination. All attempts should be logged with Login attempted, date attempted and IP Address it came from. You can easily see when someone has attempted to brute-force your login system without gaining entry.
Take all those in account when creating new or building on existing Asp.net websites/web applications – and you’ll be helping provide a more secure and safe website.
Download a trial of Visual Studio 2010.
About the author
Stephen Aitchison is senior developer at Aura Redeye Security Ltd. You can find him on Twitter as @NZCoderGuy and on Geekzone as well.
Take for example the ForumsList method of the Geekzone API, which will (oddly enough) return the list of available forums, and their associated details such as a description, topic and post counts, etc.
Lets mock up how we would consume this service call. First, we'll create a local class structure in our project - into which we are able to map the results we expect back from our API call. In this case we'll create a 'Forum' class. We will be serializing our JSON results into this class, giving us a nice, friendly, strongly typed interface to work against (we like those).
Next we'll add a reference to the JSON.NET project (in this case I'm using Nuget to do so).
Then, using the WebClient class of the .NET Framework, we initiate an asynchronous HTTP GET request to the API URL, which will result in a JSON response string being returned.
In this case, what we have returned is a JSON string representing a collection of forum results. You'll also see within the structure that there are fields which match up perfectly with our 'Forum' class we created earlier (what a co-incidence). This convention means we'll easily be able to auto-magically map these strings into our strongly typed class structure.
Now using the JSON.NET converter class to serialize our string of textual information into a class structure we are left with a 1 to 1 mapped object which retains all hierarchy and structure ready to be used.
So there we go, a couple of small method calls and a little help from our friend JSON.NET and we're consuming a REST API and mapping results to nice friendly objects.
PS. Lookout for additions to the Geekzone API coming soon (including better documentation!).
Download a trial of Visual Studio.
About the author
Phil Gale is a Software Architect and Graphic Designer with over a decade of hands on experience in the web and software industry. He is a director at Red Jungle where they make fantastic software with exceptional user experiences. You can catch him twitter at @redjungle and on Geekzone as well.
Each of these environments will typically (at least hopefully) have its own version of the database (usually on a different server, especially for production), and other settings that logically need to vary from one environment to another (the most obvious being for instance whether or not "debug" is enabled). There may additionally be different mail settings, different web service endpoint settings and so on.
Managing these differences has been tedious and error-prone to do manually, and not exactly a piece of cake with automated systems either (I remember having to include post-build steps to copy and rename configuration files, for instance).
Fortunately, Visual Studio 2010 includes a feature which improves this situation considerably.
If you create a new project using one of the Web templates (such as ASP.NET Web Application or ASP.NET MVC 3 Application for example, but not Web Site) and glance at the Solution Explorer you'll notice an arrow next to the Web.config, indicating the presence of dependent files. If you expand this arrow you'll see the following:
If you now open Web.Release.config, you'll see something like this:
Note the unfamiliar xdt:Transform attribute on the element - this has the value "RemoveAttributes(debug)", and it does exactly what it says: it is an instruction to remove the debug attribute from the compilation element. Since we do not typically want out production code to run as debug, this makes sense for the release version of a config file.
By default, any values in the original Web.config file not explicitly removed, overridden or modified will carry through to the final output, so the only things you need to specify explicitly in the transformation files are those you want to add, remove or change.
If you look at the commented-out examples in the Web.Release.config file (and I suggest you do as a good place to start), you'll notice that the first example shows a section containing an entry for a "MyDB" connection string, and in addition to the xdt:Transform attribute we have already seen there is an xdt:Locator attribute, with the value "Match(name)", which as you can probably guess instructs that in selecting the element to modify, it should be matched according to the name attribute of the element.
A connectionStrings section may contain multiple connection strings, so to identify which one you want to apply a particular transformation to you use a Locator attribute (the same applies in other cases where there is potential ambiguity - note that you didn't need one on the element because there is only one.
The Web.config transform is applied when the application is published - one obvious way to try this out is to select "Build->Publish " from the Visual Studio menu, and then use the publish method of your choice - I find that publishing to the local file system is a good way to verify results quickly.
The Web.config transformation applied is the one corresponding to the currently selected build configuration - so for instance to apply the transformations specified in Web.Release.config you would publish with the build configuration set to Release. If you add additional build configurations (which if you use automated builds you probably will) you can generate additional configuration transform files, which will be named to reflect the new or additional build configurations.
If for instance you use the Configuration Manager to create a new build configuration named "Test", you will find that when you right-click Web.config the Add Config Transforms context menu entry is now enabled. If you click this option it will generate a Web.Test.config file (as well as config transform files for any other build configurations you may have created).
Note that if for example you chose to base your hypothetical Test build configuration on Release (which is what I generally do) it will generate a Web.Test.config file that is a duplicate of the default (unmodified) Web.Release.config file.
If we go back to our Web.Release.config file, remove the comments around the connectionStrings section and publish with build configuration set to Release, you may possibly be surprised by the result. The output Web.config file includes an ApplicationServices connection string because it is included in the project's Web.config file, but it does not include the MyDB entry that we added in Web.Release.config - this is because the xdt:Locator attribute is set to "Match(name)", and there is no existing connection string with a name attribute of "MyDB", so the match fails.
We can fix this by adding a "MyDB" connection string in the project's Web.config and leaving its connectionString attribute as an empty string. This is a good approach when an element such as a connection string is present in all build configurations but we want to give it different values in each (or for given subsets). If on the other hand you wanted to add a completely new connection string in one configuration (unlikely in the case of connection strings, but there are other elements where it would make sense) you would omit the xdt:Locator attribute and give xdt:Transform the value "Insert".
So what else can you do with xdt:Transform?
Possible values are as follows: Replace (replaces the matching element, or the first of a series if there is more than one match), Insert (inserts a new element at the end of the selected collection), InsertBefore (followed in brackets by an absolute XPath expression used to identify the element before which it is inserted), InsertAfter (similar to InsertBefore except for the position at which it inserts), Remove (removes the selected element or the first of a matching), RemoveAll (removes the selected element or elements), RemoveAttributes (removes the specified attribute or a comma-delimited list of attributes - this is the transform that is enabled by default for the element's debug attribute in Web.Release.config) and SetAttributes (allows you to change selected attributes to the values they have on element containing the SetAttributes attribute, without replacing the elements containing those attributes).
More on xdt:Locator
The examples of matching I've shown have been simple matches on the value of an attribute, but the Locator syntax is actually much more flexible than that. "Match" can take not just a single attribute but a comma-delimited list, and for more complex matches you can instead use "Condition" or "XPath": both take an XPath expression as their argument, but whereas with "Condition" the expression evaluates a path relative to the selected element, with "XPath" it is absolute and applies to the entire configuration.
MSDN documentation covering Transform and Locator syntax (with examples) can be found here.
Publishing with Automated Builds
While it's all very well being able to publish a web application from your PC and have transforms applied as part of that process, in the real world (at least the nice part of the real world, where we all wish we lived) the finished web application will be built from source control by an automated build process and then deployed, perhaps as the final step in that process.
Microsoft are very fond of people using deployment packages to deploy web applications, and their online documentation covers using web config transforms with deployment packages in some detail (this is a good place to start). If that's what you're using you should be fine (if there are any issues with the build automation, it's worth checking out this thread on stackoverflow.com).
However, if your build process simply builds the web application for XCopy deployment (which I'm certain is a very common scenario) you may be wondering how to cause the transformation to be applied, since in this case the build is not performing a "Publish" as such. Fortunately, you can handle this situation fairly easily by adding an AfterBuild step to your project file that executes TransformXml and then following the transform cleans up by deleting all every file from the output that matches the pattern "Web.*.config" (therefore leaving your output Web.config file and deleting the transform files, which you are unlikely to want to deploy to the web site). I encountered this issue myself and resolved it as described a little over a year ago, so you can find the solution described in some detail on my blog.
Download a trial of Visual Studio 2010.
About the author
Kevin Daly has been writing code professionally since 1986 and for kicks since about 1981. He has been using .NET and C# continuously since .NET 1.0 was still in beta (2001 For Those Who Came In Late). His programming interests span desktop, web and mobile development, but he is particularly interested in the XAML-based (or at least XAML-aware) technologies such as WPF, Silverlight and WinRT. He is also interested in creating legions of killer robots (although that one's been slow getting off the ground). Other examples of his views, rants and even the odd code sample can be found on his blog at http://kjdaly.com. He will now stop talking about himself in the third person because it's frankly a bit weird.