Felix "FX" Lindner
Citibank does not play dice
Non-random TANs weaken online banking security
The whole point of randomly generated numbers in security situations, such as the TANs used in banking, is that they should be immune to prediction. TANs generated by Citibank fall far short of this, and unnecessarily put customers at risk.
There are people with exceptional intellectual resources, sometimes called beautiful minds, who see patterns where others see noise. On the other hand, these people often fail to understand the implications or causes of the pattern, especially if they contribute to the pattern being there in the first place. You would expect such people to break an algorithm by simply looking at its output.
But if one of us simple-minded individuals looks at a supposedly random set of data and can tell how it is generated, even predict how the series continues, the algorithm really fails its purpose. And if the random data is part of a one-time pad security mechanism many people rely on, it makes matters even worse.
TAN, short for Transaction Number, is a one-time pad mechanism used in Germany and other countries for securing online banking transactions. The customer receives a list of 6-digit random numbers via snail mail. The bank keeps a copy of this list on their systems. For every transaction, the customer must enter one of the random numbers and the banking system checks if that number is on the current TAN block for the customer. After the transaction, the TAN is invalid and cannot be reused. The customer scratches the TAN from his list.
Online banking customers are educated on a regular basis by their banks that the TAN mechanism is, besides the static PIN (Personal Identification Number), the primary security barrier. No attacker could circumvent it, due to its one-time nature. It follows that a used TAN is not considered a secret, because it's supposed to be useless. Some banks, such as Deutsche Bank, even display the used TAN together with the transaction summary, knowing it might end up in the browser cache.
Recently, I had to start a new TAN list for Citibank Online Banking, since my old one was used up. Citibank had sent me a new list when the old one had only a few TANs left on it, and so the new list dated back to April 2005. Once I entered the first few of them, I realised that they all start with the same digit, which is odd for a random data set.
Reading the TAN list in rows, it became painfully obvious that the numbers were simply increasing by a small random amount between 167 and 1348, 263 in average. This is a very small change for numbers with a key space of 10^6. I scanned the TAN list and fed the image into OCR software to get the raw numbers. When plotting the difference between two consecutive numbers, I obtained a graph with a clear tendency around 200.
As a counter example, I also plotted a graph of an equally large set of 6-digit numbers generated by the following Perl script:
srand( time() );
for ( $i = 0; $i < 200; $i++ )