Saturday, December 5, 2009

Password Expiration is a Meaningless Ritual

There are many examples throughout history where a once meaningful rule over time outlives it's original usefulness and becomes meaningless ritual. Password changing policies in a modern network of independent computer like a typical corporate network is such an example today.

A password changing policy is that annoyance that you are faced with every 3, 6 or 12 months typically when you get a notification stating that your password is about to expire and you have to change it.

Now, why is that a meaningless ritual? Because the original justification no longer applies. This practice originated in a system of time shared central computers, your IBM mainframe or VAX/VMS mini(!) computer. You connected to this central beast using a fairly dumb synchronous or asynchronous terminal. The distintive feature of these terminals were that they did not load and exectute arbitrary code. They just displayed information as it was sent to them. To gain access to a system or an application, you started this application on the central computer, and it then asked you for your credentials, i.e. user name and password. If it was ok, it let you access the system. It was all fairly similar to the DOS-box we have in todays Windows computers.

In these days of central IT departments and limited number of terminals, it was common practice that if you went for a vacation, or had to take sick leave, you'd let your collegue use your login information to help complete the tasks that needed completing. This of course led to a situation over time where you essentially lost control over who actually had access to your logon credentials and could use your account. So, to minimize the effect of this, IT departments invented password aging and expiration, forcing you to change it every now and then. This actually had an effect, because if someone with bad intentions actually had gained access to your password, it now become worthless (unless of course, you do as most people did then and still do - use a consistent theme for your passwords, since you can't be bothered to invent and remember a really new one every time).

So, back to why this practice now is a meaningless ritual. Because the password no longer is limited to giving access is to a central system via a non-programmable terminal. Today, the password typically gives you the right to install and execute arbitrary code in the actual computer used to access the systems in question! Anyone with any kind of security training knows that if someone once has had access to a computer with enough privileges to run and install software, that computer is forever potentially compromised until it is reinstalled from original operating system media.

Does changing the password acutally enable you to regain control over your system? Is that the recommended practice if you've had a virus or other malware in your computer? Change the password? Of course not! It's a meaningless gesture changing nothing. Your system will remain potentially compromised until you reinstall the original software from scratch.

So, if you're and IT department manager why would you want to implement a password expiration policy? The only reason I can think of is because it feels good, and because it's way we've always done it. It doesn't actually improve the security of your network one single bit. Not at all. It does annoy the users, and gives you a certain sense of power of course! That's always something.

What should you do instead, provided you're constrained to passords?

  • Set up a password complexity policy that is tough enough that a dictionary attack is unlikely to succeed. Go for length rather than require special characters etc. 15 characters or more is probably a good idea.
  • Set up a password change policy to the effect that the password never expires and cannot be changed by the user - yes, the opposite of what is probably the most common policy today!
  • The best is to generate passwords for your users - yes, you select them! Use a password generator that produces passwords that are not just random collections of characters, but rather combinations of characters that are possible to remember. Give the new user the password an a piece of paper, and keep no copy for your self.
  • Explain to the new user that this is the password, it's ok to keep the paper in the wallet for a few weeks until it sticks to memory. In return for this rather tough password complexity, the user will never need to remember another password while employed by this company. That's a fair tradeoff!
  • Also explain that this password may not be re-used at any other location, that it's a breach of company security IT policy to do so. The password is in effect company confidential and privileged information that may not be disclosed to any third party.

Now, if you get into the situation that the password is considered compromised, this will most likely be because of a malware infestation in your corporate network, it's fairly obvious that you both have to clean all the systems and change all the possibly compromised passwords. But only then! And the reverse applies too, if you have a suspicion that the password is compromised, you should consider all systems where this user has logged on as compromised and candidates for reinstallation.

So, let's start to modernize our policies and actually make them mean something instead of going through old and meaningless rituals!

Update your password policies today!

Sunday, March 1, 2009

How not to shuffle a deck of cards with LINQ

I’m an avid reader of MSDN Magazine, and seldom find any errors. However, in Ken Getz's article “The LINQ Enumerable Class, Part 1” in the July 2008 issue, I found a rather glaring error that needs correction. I sent the following text to Ken, but unfortunately never got a response. Hopefully some will see this blog post, and we'll not be seeing the error illustrated here in production code.

The following piece of code intended to solve the classic shuffle problem is very wrong:

Dim rnd As new System.Random()
Dim numbers = Enumerable.Range(1, 100), OrderBy(Function() rnd.Next)

The error will manifest by making some shuffles more or less likely than others. It is not an unbiased shuffle.

The problem lies in the fact that a list of 100 random numbers, independently chosen, are used to produce a random order of the numbers 1 to 100.

If this code is used as a template for a simulation, the results will be skewed, because not all outcomes of the shuffle are equally likely. If the code is used (with appropriate substitution to a strong pseudo random number generator) for gaming software, either the players or the casino will get better odds than expected.

This is rather serious, as code snippets from MSDN Magazine are likely to be used in many applications.

Why is the code wrong?

Because, when shuffling N numbers in random order, there are N! number of possible shuffles. But, when picking N random numbers independently, from a set of M numbers, there are M**N possible outcomes due the possibility of the same number being drawn more than one time.

For there to be a possibility of this resulting in all shuffles being equally likely, M**N must be evenly divisible by N!. But this is not possible because in this particular case M, 2**31-1 or 2,147,483,647, is prime! System.Random.Next() will return a value >= 0 and < Int32.MaxValue, so there are Int32.MaxValue possible outcomes, which is our M in this case.

This is a variation of a classic implementation error of the shuffle algorithm, and I’m afraid that we’ll have to stick with Fisher-Yates shuffle a while longer. Changing the code to use for example Random.NextDouble() does not remove the problem, it just makes it a bit harder to see. As long as the number of possible outcomes of the random number sequence is larger than the number of possible shuffles, the problem is very likely to be there although the proof will differ from case to case.

There are many more subtle pitfalls in doing a proper shuffle, using the modulo function to reduce integer valued random number generator outputs or using multiplication and rounding to scale a floating point valued RNG just being two of the more well-known.

By the way, the actual implementation of System.Random in the .NET Framework is quite questionable in this regard as well. It will not return an unbiased set of random numbers in some of the overloads, and the Random.NextDouble() implementation will in fact only return the same number of possible outcomes as the System.Next(), because it just scales System.Next() with 1.0/Int32.MaxValue.