千家信息网

如何理解PHP中的随机数安全问题

发表于:2026-10-31 作者:千家信息网编辑
千家信息网最后更新 2026年10月31日,这期内容当中小编将会给大家带来有关如何理解PHP中的随机数安全问题,文章内容丰富且以专业的角度为大家分析和叙述,阅读完这篇文章希望大家可以有所收获。1、引言西湖论剑杯线上预选赛线上赌场一题,明文攻击出
千家信息网最后更新 2026年10月31日如何理解PHP中的随机数安全问题

这期内容当中小编将会给大家带来有关如何理解PHP中的随机数安全问题,文章内容丰富且以专业的角度为大家分析和叙述,阅读完这篇文章希望大家可以有所收获。

1、引言

西湖论剑杯线上预选赛线上赌场一题,明文攻击出来的hint中给了/flag/seed.txt以及一个字符串code,这里需要稍微脑洞一点想到seed是指随机数种子,以及Web页面上的code值是每小时更换的"随机数":


我们利用phpmtseed工具(C编写,速度很快)可以根据随机数碰撞出随机数的种子,从而获取flag:

以下是原理分析:

2、随机数的安全缺陷

随机数广泛应用于生成验证码、Token、密钥等场景中,分为真随机数和伪随机数。我们通过算法(常用线性同余)和种子(常用时钟)得到的随机数属于伪随机数:当知道种子或已产生的随机数时,随机数序列是可以被预测的。


可以看到PHP Manual其实提示了生成随机数用于加密是不安全的,但是这个Caution不知为何只存在于英文版的PHP Manual中,中文版被遗漏了...这可能也是很多国内的开发应用出现过此缺陷的一个原因。

PHP中生成随机数的函数有rand()和mtrand(),它们分别对应srand()和mtstrand()两个用于播种随机数种子的函数。我们建立rand.php进行测试:


  1. mt_srand(2333);

  2. srand(2333);

  3. echo "seed=2333,rand()产生的随机数序列:\n";

  4. for($i=1;$i<=3;$i++){

  5. echo rand()."\n";

  6. }

  7. echo "seed=2333,mt_rand()产生的随机数序列:\n";

  8. for($i=1;$i<=3;$i++){

  9. echo mt_rand()."\n";

  10. }

  11. ?>

执行:



可以看出当随机数种子相同时,不管是rand()还是mtrand()产生的随机数序列都是相同的,如果seed泄露则会导致随机数序列的泄露。当种子值为固定如mtsrand(1000)时,随机数形同虚设;而使用动态种子也未必安全,如:


  1. //seed值较小,直接遍历爆破

  2. mt_srand(mt_rand(0,1000));

  3. //用公开的time()作为种子,和静态种子一样危险

  4. mt_srand(time());

  5. //破解时要注意服务器时间可能存在偏差,需要设定一个较小的范围

自PHP 4.2.0 起,随机数发生器会自动完成播种,不再需要手工调用srand()或mt_srand(),但是这样仍旧不安全,我们分别对两个函数进行讨论

3、rand()

rand()在产生随机数时不会自动调用srand(),产生的随机数序列可以通过这个式子预测:

state[i] = state[i-3] + state[i-31]

所以我们可以收集rand()生成的32位以上的随机序列,以预测后面的随机序列。

详细参考:Cracking-Php-Rand

(http://www.sjoerdlangkemper.nl/2016/02/11/cracking-php-rand/)

并且在某些平台下rand()最大值为32767,非常容易遭到爆破。

4、mt_rand()

根据PHP Manual,mtrand()产生随机数值的平均速度比libc提供的rand()快四倍,rand() 函数默认使用 libc 随机数发生器,mtrand() 函数是非正式用来替换它的。

mtrand()函数的安全缺陷主要出现在,所谓"自动播种"其实是PHP在同一个请求进程中只会进行一次播种,也就是说即使多次调用mtrand()函数,也只会根据第一次播种的种子生成随机数。这一结论的证明可以通过mt_rand()的源码分析或写个小脚本测试来完成,不再展开,函数的核心实现代码是这一部分:


  1. PHPAPI void php_mt_srand(uint32_t seed)

  2. {

  3. /* Seed the generator with a simple uint32 */

  4. php_mt_initialize(seed, BG(state));

  5. php_mt_reload();

  6. /* Seed only once */

  7. BG(mt_rand_is_seeded) = 1;

  8. }

  9. /* }}} */

  10. /* {{{ php_mt_rand

  11. */

  12. PHPAPI uint32_t php_mt_rand(void)

  13. {

  14. /* Pull a 32-bit integer from the generator state

  15. Every other access function simply transforms the numbers extracted here */

  16. register uint32_t s1;

  17. if (UNEXPECTED(!BG(mt_rand_is_seeded))) {

  18. php_mt_srand(GENERATE_SEED());

  19. }

  20. if (BG(left) == 0) {

  21. php_mt_reload();

  22. }

  23. --BG(left);

  24. s1 = *BG(next)++;

  25. s1 ^= (s1 >> 11);

  26. s1 ^= (s1 << 7) & 0x9d2c5680U;

  27. s1 ^= (s1 << 15) & 0xefc60000U;

  28. return ( s1 ^ (s1 >> 18) );

  29. }

由于根据种子生成随机数序列的计算并不可逆,有效的破解方法应该是穷举种子并生成随机数序列,与已知的随机数(序列)作比较,这也是文章开头提到的phpmtseed工具的实现逻辑。

5、安全建议

涉及到加密/权限/CSRF Token等敏感操作时:

  • 不要使用时间函数作为种子或直接作为随机数:time()/microtime()

  • 不要直接使用rand()``mt_rand()这样的弱伪随机数生成器

  • 随机数要足够长以防御暴力破解

上述就是小编为大家分享的如何理解PHP中的随机数安全问题了,如果刚好有类似的疑惑,不妨参照上述分析进行理解。如果想知道更多相关知识,欢迎关注行业资讯频道。

随机数 种子 序列 函数 安全 生成 分析 缺陷 问题 相同 两个 内容 发生器 可以通过 工具 常用 文章 时间 速度 加密 数据库的安全要保护哪些东西 数据库安全各自的含义是什么 生产安全数据库录入 数据库的安全性及管理 数据库安全策略包含哪些 海淀数据库安全审计系统 建立农村房屋安全信息数据库 易用的数据库客户端支持安全管理 连接数据库失败ssl安全错误 数据库的锁怎样保障安全 科技互联网 互联网科技网 互联网佳科技有限公司 科技互联网技术 互联网与未来科技 贷财互联网科技 朗涯互联网科技 上海喔噻互联网科技 互联网科技公司名称 上海电发互联网科技有限公司 科技赋能互联网健康 西安小鹰速贷互联网科技有限公司 互联网科技公司营业执照怎么办理 中科明德北京互联网科技 山东子淼互联网科技有限公司 雨阳互联网卡科技有限公司 广东工业互联网大赛深圳学泰科技 广州梦谷互联网科技有限公司领导 银川新华互联网科技学校原画 科技互联网经济论坛 互联网科技汛 创业天下互联网科技有限公司 央行互联网金融科技公司 云南省自由互联网科技有限公司 宇信科技在杭州互联网排第几 广州有谷有贝互联网科技有限公司 福建互联网展示科技馆设计 悟空问答互联网科技 数字互联网科技有限公司 科技美学互联网 艺术
0