千家信息网

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

发表于:2024-09-22 作者:千家信息网编辑
千家信息网最后更新 2024年09月22日,这期内容当中小编将会给大家带来有关如何理解PHP中的随机数安全问题,文章内容丰富且以专业的角度为大家分析和叙述,阅读完这篇文章希望大家可以有所收获。1、引言西湖论剑杯线上预选赛线上赌场一题,明文攻击出
千家信息网最后更新 2024年09月22日如何理解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安全错误 数据库的锁怎样保障安全 儿童发展研究数据库 网络安全笔记本要求 苏州python软件开发价位 七日杀服务器管理软件 服务器补丁更新 管理器 互联网金融科技工作 如何连接金蝶云服务器 朱海仑关于网络安全指示 打印机服务器控制打印权限 软件开发必须指定数据库怎么写 vs2008如何连接自带数据库 文件服务器文件夹权限详解 华宇职业学院网络技术哪个好 怎样才能加强网络安全管理 赛龙网络技术有限公司 数据库和系统工程师 网络技术注释 苏州阿里云服务器开发状况 服务器断电挂载磁盘错误 网络安全责任书的范文 大数据时代数据库技术 饥荒服务器卡顿主要原因 配置一个安装服务器失败 永康市飞牛网络技术有限公司电话 幻塔星岛服务器是哪里下载 不同部门之间的网络安全性 基准网络技术是什么 数据库中怎么备份 常熟正规网络技术服务费 违网络安全法第二十七条
0