Development

#7018 ([PATCH] Extremely weak random generator for RememberMe keys)

You must first sign up to be able to contribute.

Ticket #7018 (reopened defect)

Opened 7 months ago

Last modified 3 weeks ago

[PATCH] Extremely weak random generator for RememberMe keys

Reported by: laurentb Assigned to: fabien
Priority: major Milestone:
Component: sfGuardPlugin Version:
Keywords: Cc:
Qualification: Unreviewed

Description

Current function:

  protected function generateRandomKey($len = 20)
  {
    $string = '';
    $pool   = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';
    for ($i = 1; $i <= $len; $i++)
    {
      $string .= substr($pool, rand(0, 61), 1);
    }

    return md5($string);
  }

There are may issues with this random generator. The $string construction is using an extremely weak method; rand() is also not a good choice. md5() is known for its collisions.

Indeed, on a test database with 1500 Remember Me keys, we have about 40 keys assigned to multiple users (up to 3).

Here is my proposal of a much stronger generateRandomKey() function:

  protected function generateRandomKey()
  {

    return base_convert(sha1(uniqid(mt_rand(), true)), 16, 36);
  }

It will return a 31 character string using alphanumeric characters (base 36), thus it will fit in the 32 character limit which was used by the md5 (hexadecimal, base 16).

sfDoctrineGuardPlugin is also affected.

Change History

08/17/09 12:30:19 changed by laurentb

Users who wants the fix right now can create a sfGuardSecurityUserFix class containing:

class sfGuardSecurityUserFix extends sfGuardSecurityUser
{
  /**
   * generateRandomKey without collisons.
   * @see sfGuardSecurityUser::generateRandomKey
   *
   * @author Laurent Bachelier <laurentb@theodo.fr>
   * @return random alphanumeric characters
   */
  protected function generateRandomKey($ignored = 20)
  {
   
    return base_convert(sha1(uniqid(mt_rand(), true)), 16, 36);
  }
}

And change their myUser classes to extend sfGuardSecurityUserFix.

They should also delete their RememberKeys? having collisions.

11/19/09 22:52:55 changed by alecs

  • status changed from new to closed.
  • resolution set to invalid.

performed a test to obtain 600000 results ... no duplicate.

11/20/09 01:26:23 changed by laurentb

  • status changed from closed to reopened.
  • resolution deleted.

It did not try to reproduce it since by just reading the code anyone should figure out that both md5() and rand() are a bad idea, and that calling rand() multiple times is even worse. I forgot about it until then.

I hope you just did not do a simple for() to test it since calling rand() one time per PHP instance is completely different from running it multiple times (seeding occurring once vs. occurring each time).

I did try with that piece of ugly but effective code:

<html>
<head>
<meta http-equiv="refresh" content="1" />
</head>
<body>
<?php
// paste generateRandomKey() here

$plop = file_get_contents('plop.txt');
$plop .= "\n".generateRandomKey();
file_put_contents('plop.txt', $plop);
?>
</body>
</html>

Anyway, I was able to reproduce it, but not on my system (PHP 5.2.11-pl1-gentoo). Maybe I could with more tries.

Here is the affected system:

PHP 5.2.9-0.dotdeb.0 with Suhosin-Patch 0.9.7 (cli) (built: Mar  9 2009 21:45:18) 
Copyright (c) 1997-2009 The PHP Group
Zend Engine v2.2.0, Copyright (c) 1998-2009 Zend Technologies
    with XCache v1.2.2, Copyright (c) 2005-2007, by mOo
$ sort plop.txt|sort -u|wc -l
1062
$ sort plop.txt|wc -l        
1289

Yep, more than 200 duplicates.

After replacing the function:

$ sort plop2.txt|wc -l
1144
$ sort plop2.txt|sort -u|wc -l
1144

Zero duplicates.

Something is probably wrong on this server. However, the difference of the number of duplicates between the two implementations is pretty much clear.

11/20/09 02:01:24 changed by laurentb

You should also note that rand() under Windows is even worse! http://www.boallen.com/random-numbers.html

02/08/10 00:22:49 changed by francois

Up. This really deserves some attention, and the fix is easy.

By the way, laurentb made this flaw even more public than it was just for this ticket in a blog post this week - and he's right to.

02/26/10 11:14:56 changed by fabriceb

Up.

First I witnessed the bug.

And ok it is a vicious bug because it depends on the platform, but nonetheless there is no reason to leave a lousy random number creation done "with the hands" in symfony's code.

The Sensio Labs Network

Since 1998, Sensio Labs has been promoting the Open-Source software movement by providing quality web application development, training, consulting.
Sensio Labs also supports several large Open-Source projects.