且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

PHP 的 rand() 函数是否曾被用作漏洞利用?

更新时间:2023-09-11 21:58:04

在 PHP 7 之前,PHP 使用 LinearCongruential Generator 算法生成一个随机数或简称 LCG.该算法的工作原理如下:

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

当你第一次做随机数时,显然没有previous_random 数.这就是我们提供种子的原因.所以,种子只是第一个 previous_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.

现在,我们知道了算法,但我们需要知道 PHP 使用的 acm 的值是什么.我相信每个版本的 PHP 都使用不同的值.但是假设我们不知道这些值,我们如何猜测这个值.就我而言,我使用的是 PHP 5.6.15 Windows.

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

所以,m = getrandmax() + 1.由于我们的种子是 0,所以我们的 c = 12345.为了得到值a,我们可以使用简单的循环来猜测a.

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

或者你可以像这样获得价值a

or you can get value a like this

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

现在,我可以编写与当前 PHP 版本相同的随机函数.

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;
    }
}

不过

我能够预测我自己的 PHP 版本,因为我对我当前的环境有很多了解,我知道一些以前的随机,我知道种子.如果攻击者的知识几乎为零,就不容易被攻击.

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.

PHP 7.0+,默认使用 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.

取决于您向公众公开了多少信息.如果你只生成一个随机数,而攻击者不知道 aprevious_randomcm.攻击者不可能预测下一个随机数.

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.