Is using microtime() to generate password-reset tokens bad practice
Asked Answered
S

3

6

In PHP I've noticed some frameworks make use of the microtime() function to generate password reset tokens as in:

  $token = md5(microtime());

Is this a security issue? If the attacker is able to synchronize the clocks with the server to a degree of accuracy they could brute force the token. 1sec synchronization will only require 1,000,000 tries and this is not too crazy of an issue.

How likely is this attack to succeed? Should one be generating tokens with /dev/urandom or openssl_pseudo_bytes() instead? Is microtime() bad practice?

Snail answered 20/3, 2013 at 15:23 Comment(1)
why not md5(microtime().mt_rand()); ?Billion
F
4

Yes it is a security issue! Generating tokens with time is a very bad practice. Burp Suite makes it trivial for an attacker to brute force tokens that are predictable, and tokens based on time are very predictable. Burp allows someone to easily gather tokens and perform statistical analysis on them to determine entropy. Using this info you can easily predict future tokens.

Remember, the attacker only needs to get it right once. Getting it wrong millions of times makes no difference.

Here is a useful (and recent) StackOverflow post about token generation that may be helpful to you: REST Web Service authentication token implementation

Fidel answered 20/3, 2013 at 17:22 Comment(0)
A
0

Tokens should always be created at random, not microtime. Now to give some extra securty (because, let's face it once again: computers cannot do anything but calculate stuff), you'll want to see php's example: http://php.net/manual/de/function.srand.php Also see http://php.net/manual/de/function.chr.php to easily create a "completely" random string. Here's how I do it

mt_srand((double) microtime() * 1000000);
    function random_string ($length = 16)
    {
        $string = "";
        for ($n = 0; $n < count($length); $n++) $string .= chr(rand(32, 126));
        return $string;
    }
Algesia answered 20/3, 2013 at 15:32 Comment(1)
“Tokens should always be created at random, not microtime.” – And you seed MT with microtime? By the way: “Note: As of PHP 4.2.0, there is no need to seed the random number generator with srand() or mt_srand() as this is now done automatically.Underestimate
A
0

Yes, it is (I think).
A hacker might able to guess the password in 1 to 2 hours. (If the server use a limit how much resets can be taken the hacker can avert it by using a Botnet or with having a lot of time and lots of trials.

If I were you I would add a static salt. The salt should be loaded from a config (or an other secure place). The salt should not be set by the server own or whoever. It should be generated by a real-random API (google should help you but I guess random.org offers one).
If you are not able to use that API a pseudo salt should help, too as long as the hecker don't know when the server has been set up (or the server admin might delete it sometimes, but not automatic!)

Example:

$salt = null;
include('protectedDir/salt.php'); // Here should stand "$salt = ''"
if ($salt == null){
// Using real random api
file_put_contents('protectedDir/salt.php', '<?php \$salt = \'$salt\'; ?>)";
}

$resetKey = sha1(microtime() . $salt);

// May contain bugs. Untested. It is only a example and should not be implemented by copying and pasting.

If the hack has access to the php file ('protectedDir/salt.php') "source code" he should be able to see database configs, too. And it would be an bigger problem.

Aero answered 20/3, 2013 at 15:50 Comment(1)
Good thinking, although I'm not sure a static salt would be helpful in this case because the entropy is very low (and it is 100% predictable). To be effective the salt would need to be dynamic and very random. It seems to me it's better to just make the entire token completely random.Fidel

© 2022 - 2024 — McMap. All rights reserved.