I want to write a patch for a two factor authentication system that someone else has started. The code is a module for a PHP content management system and sends an SMS message to a user's phone, after they successfully enter a username and password. If the user then types the code into the site, they get logged in.

The main part missing from the module is the random code generator. I was considering basing the generator on the Second Factor plugin for WordPress. Specifically, the second_factor_regenerate_token function does essentially what I need. Is the method used by that function relatively safe? Is there anything I should pay special attention to when adapting it?

  • 2
    Hi @Matt, welcome to Information Security! You should note that this isnt really "two factor" authentication, it's "out of band" authentication. True two-factor would require either some form of biometrics, or "something you have". A cell phone by itself would be questionable IMO as "something you have", not to mention that there are other issues preventing this from being a true 2nd factor. (That's not to say that out-of-band is necessarily bad... ) – AviD Feb 23 '12 at 12:56

Summary. No, that code does not look safe. It doesn't have enough entropy that will be unpredictable to the adversary. I would not re-use that code.

The right way to do it. To generate a random code, I suggest that you read the desired number of bits from /dev/urandom. This is a one-time code, and it needs to be random and unguessable and cryptographically strong. That's exactly what /dev/urandom provides. The OS manufacturer has already worked out how to do this securely, after great thought, and that approach has been vetted by security experts. I suggest you simply re-use their existing work.

Analysis of second_factor_regenerate_token. I don't know if I'm understanding the code properly, but it looks like it doesn't have enough entropy. It hashes the user's username, user's password, HTTP headers, and the current time. That's not enough entropy.

Remember that the purpose of a second factor is to prevent unauthorized individuals who somehow have come to know the user's username and password from gaining access to the system. (If the unauthorized individual doesn't know the user's username and password, then we don't need a second factor; the first factor already blocks them.) So our analysis should start from the assumption that the attacker knows the user's username and password.

Once we make that assumption, the only remaining entropy comes from the current time and the HTTP headers. The time definitely does not have enough entropy: it will be known, or almost known, to the attacker (possibly off by a few seconds, due to imperfect time synchronization, but the attacker can just try all possibilities). I don't know how much entropy will be in the HTTP headers, but it doesn't sound like a solid basis for security.

Therefore, based upon my interpretation of second_factor_regenerate_token, assuming I am correctly understanding how the code works, I do not think it represents good security engineering. I would not re-use that code.

  • 1
    I agree with your analysis of second_factor_regenerate_token: the only thing that's (in principle) not easy to guess by the attacker is the user's password. Or, in other words, the second authentication factor is directly derived from the first factor, which means it is not a second authentication factor. – Gilles 'SO- stop being evil' Feb 20 '12 at 1:33
  • 1
    Good analysis, but also take into account that if the attacker already knows the user's password, there is a decent chance he's using the user's browser too! Which would directly cause the headers to be identical, which further lowers the barrier... And you're down to time. – AviD Feb 23 '12 at 12:59

See the motivations behind HOTP, which was designed for this kind of application.

Some of your desired features are:

  • one-time passwords generated as necessary (in this case, after the user completes primary authentication)

  • feasable to send, display on the user's phone, and enter

  • feasable to verify in situations such as multiple requests for new passwords, mis-ordered or skipped sendings

  • high enough entropy (not based on knowable information such as the first factor username or password, not guessable if earlier passwords are known)

With HOTP, you store one secret key and counter per user, neither of which are sent. To generate a one-time password, you hash the key and counter, send the hash, and increment the counter. To verify a password, you hash the key and a range of counters and compare them.

You could roll your own along these lines, but HOTP is a standard. You can find reviewed implementations for your system, and can find community help to decide whether it is suitable for you.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.