简体   繁体   中英

Was there a a time when PHP's rand() function was used as an exploit?

Does anybody know if there was a time or event where somebody used rand()'s weakness in order to predict exploit it? Something like generating tokens or cheating in video games?

Since prior to PHP 7, rand() was very easy to crack. In fact here is some C code, credit to Peter Selinger, that predicts the values given a seed:

#include <stdio.h>

#define MAX 1000
#define seed 1

main() {
  int r[MAX];
  int i;

  r[0] = seed;
  for (i=1; i<31; i++) {
    r[i] = (16807LL * r[i-1]) % 2147483647;
    if (r[i] < 0) {
      r[i] += 2147483647;
    }
  }
  for (i=31; i<34; i++) {
    r[i] = r[i-31];
  }
  for (i=34; i<344; i++) {
    r[i] = r[i-31] + r[i-3];
  }
  for (i=344; i<MAX; i++) {
    r[i] = r[i-31] + r[i-3];
    printf("%d\n", ((unsigned int)r[i]) >> 1);
  }
}

So once again, was there a time when this weakness was used in order to predict the next random number and exploit something?

Thanks!

Before PHP 7, PHP use Linear Congruential Generator algorithm to generate a random number or in short LCG. The algorithm works as follow:

 next_random = (previous_random * a + c) % m
 previous_random = next_random

When you first make a random, obviously, there is no previous_random number. That's why we provide seed . So, seed is just a first previous_random value.

Now, we know the algorithm, but we need to know what the value of a , c , and m that PHP use. I believe that each version of PHP use different value for those. But let say we do not know those value, how do we guess this value. In my case, I am using PHP 5.6.15 Windows.

srand(0);
var_dump(rand());  // 12345
var_dump(rand());  // 5758

So, m = getrandmax () + 1 . Since our seed is 0, so our c = 12345 . To get value a , we can use simple loop to guess a .

$m  = getrandmax () + 1;
for($a = 0; $a < $m; $a++)
   if ((($a * 12345 + 12345) % $m) == 5758) 
       var_dump($a);  // in my case, 20077

or you can get value a like this

srand(0); rand(); // 12345
srand(1); rand(); // 32422
// so a = 32422 - 12345 = 20077

Now, I am able to write the same random function as my current PHP version.

class visal_rnd 
{
    function __construct($seed = 0) {
        $this->seed = $seed;
    }

    function rnd() {
        $this->seed = ($this->seed * 20077 + 12345) % 32768;
        return $this->seed;
    }
}

However

I was able to predict my own PHP version because I have so much knowledge about my current environment, I know a few previous random, I know the seed. If the attacker has almost zero knowledge, it would not be easy to attack.

Mersenne Twister

PHP 7.0+, by default, use Mersenne Twister . There are more parameters to be guessed than Linear Congruential Generator. So, it requires more knowledge.

Is Linear Congruential Generator Bad?

Depends on how much information you have exposed to the public. If you generate only one random number and attacker has no knowledge of a , previous_random , c and m . It is impossible for attackers to predict the next random number.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM