【问题标题】:serious bug with random numbers随机数的严重错误
【发布时间】:2014-10-07 21:27:41
【问题描述】:

我终于可以创建一种方法来重现我遇到的错误。当 2 个或更多用户同时调用一个页面时,modsecurity 会为两个用户生成相同的随机数序列(使用 php 的 rand() 函数)。

这是一个错误的演示:

http://quemfazsite.com.br/em_criacao/modelo9/teste.php

打开此页面,将加载 2 个 iframe,每个 iframe 都应该相互独立地生成随机数,但两个框架都生成相同的随机数序列!下面可以看到非常简单的源代码。如果您没有看到相同的序列,我会要求您重新加载页面几次,直到您获得相同的数字序列。

编辑:此错误仅在 modsecurity 激活时发生。如果您评论加载 modsecurity 的“LoadModule”行,则不会发生错误!

<?php

if (isset($_GET["test"])) {

        $output= "";

        for ($i=0;$i<10;$i++) {

                $output.= rand(0,99999999) . "<br />";

        }

        echo $output;

        exit();

}

?>
<iframe src="PUT_THE_SAME_NAME_OF_THIS_FILE_HERE.php?test&953487"></iframe>
<iframe src="PUT_THE_SAME_NAME_OF_THIS_FILE_HERE.php?test&234322"></iframe>

【问题讨论】:

  • 您的问题与 modsecurity 模块或 apache 完全无关。我删除了相应的标签。
  • 如前所述,它与 modsecurity 无关......这是随机数生成器的种子问题,这就是文档建议不要再使用 rand() 的原因跨度>
  • It's not mod_security。如果您没有使用不同的种子调用 srand(),那么 PHP 将使用当前的 time() 为其 PRNG 播种,这意味着如果您在同一秒内调用两个调用,您将获得相同的结果。
  • Welp,享受追逐那只大雁的乐趣。我要去调查一个相关的问题,即每当我穿毛衣时,我的车的油耗会变差。

标签: php apache


【解决方案1】:

rand 不是为生成随机数而设计的。其目的是生成在给定端点之间均匀分布的pseudorandom numbers。如果您将生成的数字制作成直方图,您会发现它们确实是均匀分布的。

生成这些数字的算法是完全确定的。如果您提供相同的种子(通常基于当前时间,如您的示例中所示),您将获得完全相同的数字序列。这是一项功能,而不是错误:它允许您利用分布的统计属性,同时能够通过重用种子来重现结果。

如果您需要随机数不可预测,您应该使用cryptographic RNG

如果您只是想稳健地避免这样的冲突(由时间衍生种子冲突引起),那么您必须检查某种跨会话存储以确保唯一性(例如文件或数据库)。如果您的应用程序要求数字始终是唯一的,那么无论如何您都应该这样做。

【讨论】:

  • 嗨,谢谢你,你是对的,我同意,但有一个问题:如果你循环 for (i=0;i
  • @Amanda rand 由当前时间播种您第一次调用它时 - 然后它会为后续调用保持状态。一旦你播种了一个伪随机数生成器,它将生成的数字序列是唯一确定的。同样,这种行为预期的。我要再次强调,如果你需要唯一的数字,你首先不应该使用rand;至少,使用基于当前微秒的冲突率足够低的哈希算法(例如sha1microtime)。 (但请注意,冲突可能仍然会发生)。
  • @Amanda 至于mod_security,我不知道它是如何工作的,但您观察到的行为差异仅与rand 的播种方式有关,仅此而已。由于rand 无论如何都是一个糟糕的功能,因此您应该寻找替代方案。我建议您在像这样使用它们之前阅读(伪)随机数生成。
  • 谢谢你帮助我,现在我理解你了。时间在第一次 rand() 中使用,其他时间取决于第一次。现在我可以理解了,但我可以向你保证,这个错误只发生在 modsecurity enable 中。我在禁用 modsecurity 的情况下进行了许多测试,但没有发生,尽管你们中的许多人已经告诉我 rand() 是一个坏函数(我同意)。如果你在没有 mod_security 的情况下在 Apache 中运行我给你的代码,你将永远不会看到一个 colison,而不是一个相等的序列......尽管你都告诉我 rand() 不好,但它会完全不同。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2018-06-14
  • 2019-04-01
  • 1970-01-01
  • 1970-01-01
  • 2019-01-05
  • 2014-04-29
  • 1970-01-01
相关资源
最近更新 更多