问题
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!
回答1:
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.
来源:https://stackoverflow.com/questions/44985462/was-there-a-a-time-when-phps-rand-function-was-used-as-an-exploit