Wednesday, January 20, 2010

One of the most common flaws I am seeing in applications is the lack of mutual authentication. Most systems authenticate that the user connecting to their system is a valid user. What is lacking is that the client verifies that it is connecting to who it thinks it is connecting to.

One of the big examples of this is WiFi. If I have a wireless router named "myrouter" and set my laptop to use that router things work great. If I go down the street and someone else has a router named "myrouter", my laptop automatically tries to connect to it. This is because the WiFi implementation does not verify that I am connecting to who I think I am connecting to.

This happens a lot on the service level of applications. The client app resolves a DNS name like www.myservice.com to it's IP address and then sends over some form of authentication. Now what happens if I somehow manage to change the DNS record for www.myservice.com to point to my IP address which contains a service with the same name and same methods exposed to it? The client will connect and divulge its authentication data to this fake service. I can now use the authentication data that you gave me authenticate against the real system and do whatever nefarious things I desire.

The solution for this is for clients to verify that the service it is talking to is actually the service you want to be talking to. This is best accomplished by using some form of shared secret. This takes on many forms but a few methods:

  1. Ask the server to answer a shifting question. i.e. ask the server to hash a certain string. If the hash the server returns matches what you expect then the server might be the one you want (or an attacker managed to replicate the algorithm)
  2. Use windows authentication. For WCF the mutual authentication is implied in this case.
  3. Use certificate authentication. This is the best way to do this task but can be a pain to implement.

Tuesday, January 19, 2010

One of the great things about continuous integration is that we can increment our assemblies version number with each build. For our project we also apply a label to our source code repository every time we build a deployment package. This allows us to get the version of source code from the exact point in time that the msi was built.

One of the issues we ran into was that we have three build configurations:
1. "CI" This gets run on every checkin of code
2. "Deploy - ALPHA" This is run manually to deploy to our alpha test environment
3. "Deploy - ALPHA & BETA" This is also run manually and this deploys the same version to both the alpha and beta test environments

The issue we ran into is that each configuration has its own build number that is incrementing so if we ran "Deploy - ALPHA" 10 times we would have v 1.10.0.0 in ALPHA. If we then ran "Deploy - ALPHA & BETA" for the first time suddenly ALPHA now has v1.1.0.0! Obviously this is not very intuitive. In the end we added in the version number from our source code repository into our build numbers for both deploy configurations. Now we get build numbers like this: 1.46347373.0.0

The way we did this was by using the vcs variable in team city: 1.{build.vcs.number.TheNameOfVCSRoot}.0.{0}. The last digit is still an incrementing counter in case you re-run the build that something still increments even though the version in source control has not changed.

Monday, January 18, 2010

One of the things we have started doing as part of our process is having a build script that creates our deployment package in an automated fashion. We then tied that into our build server so that from one click anyone could create the package. The issue is that we have several test environments and copying the setup.msi file to multiple servers and installing it is a time consuming pain. To streamline our deployment we created a vbscript (yes, it was painful) to remotely uninstall previous versions and then install the new version of the msi. Here is the script currently:

strComputer = "mytestserver"

Wscript.Echo "Getting WMI Object"
Set objWMIService = GetObject("winmgmts:" & "{impersonationLevel=impersonate}!\\" & strComputer & "\root\cimv2")

Wscript.Echo "Finding Previous versions"
Set colSoftware = objWMIService.ExecQuery ("Select * from Win32_Product Where Name = 'My First Setup Project'")
For Each objSoftware in colSoftware
    Wscript.Echo "Uninstalling a previous version"
    objSoftware.Uninstall()
Next

Wscript.Echo "Getting Software Object"
Set objSoftware = objWMIService.Get("Win32_Product")

Wscript.Echo "Installing"
errReturn = objSoftware.Install("c:\builds\MyFirstSetupProject.msi", "TARGETENV=DEVL",True)

Wscript.Echo "Install status: " & errReturn


In order for this to work the msi must be copied to the remote machine to work. I tried connecting to a central network share but it did not seem to work for me. The script needs a bit of work but now we can deploy to the environments we want updated in a couple of minutes instead of the 15-20 minutes it took us before.

Sunday, January 17, 2010

I am finally finding some time and desire to write again. Life has been busy with my both my company and my family expanding. It feels like things are starting to get back to normal again so I should be writing more frequently.

Some of the things I have been working with that I hope to write about:

  • nHibernate / fluent nHibernate / Linq to nHibernate
  • WPF
  • Click once
  • Silverlight
  • A fluent .NET build langauage called fluent-build
  • Being a lead on a project
  • Multithreading
  • Caching of large amounts of data
  • Threat modeling
  • Other security items

Monday, August 10, 2009

One thing I really like about MSTest is that you can turn code coverage on so you can see where unit tests are lacking (or non-existent).

One thing I don’t like is that in VB there is a class generated for settings in the “My” namespace. While it is handy for coding in some cases it irks me that it gets included in my code coverage result.

The only way to exclude it (that I have found anyways), is to add the DebuggerNonUserCode attribute to the MySettings class in the project. Not very intuitive I know but maybe we can get a IgnoreFromTestCoverage result attribute someday. (NOTE: I did try to create my own custom attribute but DebuggerNonUserCode is not inheritable).

This class can be found by selecting the project in solution explorer, selecting “show all files”, then finding the Settings.settings file in the “My Project” folder. Alternatively you should be able to create a partial class if you want to avoid it being lost if the code is regenerated.

Thursday, August 06, 2009

Edmonton Code Camp is happening again this year and we are looking for speakers! Topics are wide open. That means ANY language, ANY technique, or ANY technology.

When: September 19,2009
Where: Grant MacEwan Downtown Campus, Edmonton, Alberta

Please submit talks to dave@solidhouse.com by August 15, 2009

 

I was asked to review the soon to be published Brownfield Application Development by Kyle Baley and Donald Belcham. For those who have not heard the term, a brownfield application is one that already has some code developed but is usually not complete. A lot of developers are brought into projects like this and therefore have had no say on the techniques and tools to start developing the application. This book covers how to make an existing application better, more testable, and easier to work with in a simple and accurate fashion.

The book is split into two sections, the first one: The Ecosystem covers important topics like version control, testing, continuous integration, and defect tracking. The chapters were well written with no bias towards a particular technology (although the pros and cons are discussed of some systems). Baley and Belcham accurately describe how to setup an ecosystem that allows you to develop and maintain a code base well into the future.

The second section: The Code, hits home with how to bring good quality code practices into the code base. I found over and over again that the authors hit on all the problems I have seen working on brownfield and legacy code bases and great recommendations on how to overcome them.

One of the key things the authors hit on is how to minimize dependencies in your code base. Tightly coupled code is both hard to change and test which makes minimizing the dependencies very important. The best part of this book is that they have a separate chapter for reducing dependencies internally and on external systems. I find this to be the most important topics that this book covers.

I wish I would have had this book ten years ago and not had to learn these lessons the hard way. The book so accurately describes the pain points of software development and how to eliminate or mitigate those issues. The authors have obviously gone through the same learning curve that I have and have perfectly summarized their years of experience in an easy to consume format.

Thursday, July 30, 2009

One of my current clients is really embracing all the MS clones of great open source tools like MSTest, Team Build, Entity Framework, etc. Although I love the open source tools like nUnit, Team City (ok not so open source but still free), and nHibernate, I thought I would try MS Test out even though I have not heard many good things about them.

First I will say something nice: MSTest has a nice code coverage suite. I really like that it is integrated with visual studio and can even highlight the areas that are covered and not covered which is the ONE feature of MSTest that I like.

Other than that the code coverage I think MS test is a complete miss when it comes to development for the following reasons:

  • Only being able to add tests to a test project. I like my unit test classes to sit in the same project as the code I am testing as I find it easier to navigate the code, easy to spot if I did not test a class (As there is no [ClassName]Tests.cs file next to it. It appears that with MS Test I can only add tests to a test project
  • VSMDI File. When a test project is created it adds a .vsmdi and .testrunconfig file to the solution. Why these are needed at the solution level (or at all), I have no idea. Adding these items makes me have several spots to go to for changing settings instead of just one
  • Poor IDE integration. In VS I now have a test view tab, a test results tab, and a test runs tab docked into the editor (plus a code coverage tab but I can agree with this being a seprate tab). All I need is one area where I can run the tests and see the results. Just a heads up but SIMPLE THINGS ARE EASY TO USE!
  • Notification about having run more than 25 test runs. Apparently MS Test keeps 25 copies of the old tests around and when you try to run your unit tests for the 26th time you get a warning about this which is annoying. In 99% of situations you will not need to go back to the first time you ran tests so why bother even telling me?
  • Release/Debug Suprises: I had a set of tests constantly failing in the MSTest runner yet constantly passing in my Resharper runner. Also the code coverage went screwy (the code coverage was not accurate and  line highlighting did not match up). After a few hours I discovered that it was because the app was set to compile to a release but MS test just look at the debug DLL's with no warning that it is doing so. I agree that the same thing would happen with nUnit but nUnit is not integrated into the UI and is therefore not expected to be able to pick up on these things MSTest is supposed to be this integrated wonder that should know when the tests are compiled in release to maybe use the release code instead of the stale debug code (or at least warn me)
  • Hard to Navigate. When a test fails you can see some of the description of the error message but if you want further details you need to double click the item which oepns a new editor tab which explains the error a bit more. I find having to manage these tabs an annoyance and much perfer the nUnit or Resharper test runner approaches myself.
  • Hard to just run one set of tests. I have two test projects one for unit tests and one for functional tests (items that hit the database and other costly resources). It seems hard to just run tests for one of the projects. It is also hard to run tests for just one namespace. Again these things are easy with other unit testing frameworks.
  • The context menus are confusing. Right clicking on the test project and selecting "add" yeilds "New Test", "Unit Test", and "Ordered Test".
    New Test: Gives you the option of creating a new test, an ordered test, or use the test wizard
    Unit Test: launches the test wizard
    Orderd Test: creates a new ordered test
    I find the multiple routes a bit confusing (not to mention how it adds 3 elements to my already crowded context menu when I only need one)

Now these are just the issues I have had with it. A quick stop on a search engine brings up many other issues but so far I have not experienced them. I find that MSTest is not as clean, fast, or simple as other unit testing frameworks out there which makes me not want to use it on another project.

 

Tuesday, July 28, 2009

One common attack to get into a website is to brute force the username / password. This is effective mainly due to the lack of brute force countermeasures that people build into their websites login mechanism. There are a few common countermeasures out there currently.

Account Lockout

An account lockout is when a set number of failed attempts are reached that no more attempts are allowed. Usually this involves flagging the user account in your database as locked out. While this stops a brute force attack in its tracks, it does have some consequences. The most obvious is that there will need to be a mechanism to unlock the account which is usually an administrator or else a set period of time has elapsed. The not so obvious consequence is that an attacker may lock out legitimate accounts on purpose which would deny legitimate users access until the lock is released!

Tarpitting

Tarpitting is the process of slowing an attack down. Typically an attacker tries to login thousands of times per minute in a brute force attack. By putting a delay on how long it takes to get the results back you can drop the number of attacks per minute drastically. This prevents the intententional lockout attack mentioned for the account lockout countermeasure.

The most common mistake I see when implementi ng tarpitting is when it is implemented as Thread.Sleep(failedLoginAttempts * 1000). The main issue here is that the delay time keeps growing, If I wanted to prevent a legitimate user from logging in all I have to do is fail your login a few thousand times and it would then take thousands of seconds to log back in. Instead use a hard coded delay (even something like one or two seconds drops the number of attempts an attacker can perform).

The other item to worry about when implementing tarpitting is resource exhaustion. By keeping a thread sleeping you are using resources to maintain and monitor that thread. If an attacker were to be able to do enough attempts they may be able to exhaust your servers resources which could deny service to legitmiate users.

Fake That The Login Worked

This is something I theorized that may get around the negatives of account lockouts and tarpitting. What if you build a login screen that once so many failed logins were reached that it would redirect the attacker to an empty page so that the tool they are using to brute force stops as it thinks it got a hit? I have not tested this theory out but there is a bit more information here: http://www.haveyougotwoods.com/archive/0001/01/01/annoying-brute-forcers.aspx

CAPTCHA

This one is quite annoying but placing a CAPTCHA (one of those computer generated images that you have to type in the word) on the login would drastically reduce the effectiveness of an automated attack. Now the attacker has to guess the username, password, and either guess or break the CAPTCHA image which makes the attack harder. This comes at the cost of convenience and useability to the end user. Also the big downside of CAPTCHAs is that they are not usable by the visually impared.

Abandon Passwords

This is easier said than done but there are lots of password alternatives that are much harder to break than passwords. Things like certificate exchanges, smart cards, card space, and security key tokens offer better security but all have their downsides.

 

Monday, July 27, 2009

Oracle has announced that they are raising the prices on the Oracle 11g database. MS has kept the price of SQL Server 2008 the same (for now). I am still amazed that Oracle charges what they do when you can almost get two MS SQL Server licences for the price of one Oracle license. While Oracle has been shown to perform faster than SQL Server 2008 I would much rather have a system that is easier to work with and cheaper than one that I find dificult to work with and out of my clients budget range.

Here is a price comparison (NOTE: prices are based on manufacturers suggested price at the time of this writing)

Oracle   Microsoft  
Standard Edition One* 5,800    
Standard Edition* 17,500 Standard Edition  5,999
Enterprise Edition  47,500 Enterprise Edition   24,999

*the differences I could find between these two editions was that Standard Edition One allows 2 sockets and Standard Edition allows 4 sockets plus clustering and workload management.