一 、开篇

在某次复现"dedecms前台任意用户登录漏洞重现及分析"漏洞过程中, 发现这个漏洞的利用点是需要注册并审核通过一个"0000001"用户, 但在实际操作中,发现很多站点注册用户后需要邮件校验,但实际没有配置SMTP, 也就不可能发出邮件,遂分析了其邮件校验的hash生成算法, 进而发现伪随机问题,本文不会从邮件hash算法入手,而是从cookie算法分析出发, 分析漏洞的原理和利用方法. 全文分析使用dedecms v5.7 sp2, 但就漏洞本身而言是全版本均存在的。

二 、本篇简介

主要研究和分析一下在PHP5和PHP7下mtrand/mtsrand和rand/srand函数的特性, 从中找到一些结论, 方便后面对算法的分析与评估。

三、黑盒测试

针对PHP5场景下编写一些测试脚本,观察得出基本的函数特征

3.1 编写脚本:vi test_1.php

echo "rand:\n";

srand(0);

?>

运行结果:1804289383

vi test_2.php

echo "mt_rand:\n";

mt_srand(0);

echo mt_rand();

echo "\n";

echo mt_rand();

echo "\n";

mt_srand(0);

echo mt_rand();

echo "\n";

echo "rand:\n";

srand(0);

echo rand();

echo "\n";

echo rand();

echo "\n";

srand(0);

echo rand();

echo "\n";

echo "mt_rand:\n";

mt_srand(0);

echo mt_rand();

?>

运行结果:963932192

1273124119

963932192

1804289383

846930886

1804289383

963932192

3.2小结

1.mtrand/mtsrand不影响 rand/srand

2.在mtsrand的作用下,mtrand次数会重置, 在srand的作用下,rand次数会重置

3.rand和mt_rand在同seed,同次数下,值不同

四、白盒审计

针对PHP5和PHP7的C代码进行分析,选用的代码仓库如下PHP5: https://github.com/php/php-src/blob/d31e8a9a85efea54db0b647424f6c4485d71db8b/ext/standard/rand.c

PHP7: https://github.com/php/php-src/blob/becda2e0418d4efb55fca40b1170ca67cfbdb4e0/ext/standard/mt_rand.c

TIPS: 如何定位php版本对应到的源码, 可以根据php版本发布时间, 在git仓库找commit, commit时间在发布时间前一段时间的应该就是:)

1. PHP5:

1.1 rand/srand 默认使用的是C语言的原生函数:

1.2 mt_rand使用的是php实现的一套算法:

2. PHP7:

2.1 mt_rand使用的是php实现的一套算法:

2.2 rand和mtrand, srand和mtsrand完全等价:

rand.c

3. 共性:

3.1 调用一次mt_srand不仅设置了seed,而且重置了次数:

3.2 每调用一次mt_rand相当于次数+1:

3.3 调用rand,若之前没有调用srand, 那么会默认调用一次; 调用mtrand,若之前没有调用mtsrand, 那么会默认调用一次:

mt_rand:

rand:

3.4 同一进程下,在rand和mtrand均未被人工播种时, rand和mtrand使用的种子会是一样:

基于3.1, 我们能知道rand和mt_srand会默认有如下调用:php_srand(GENERATE_SEED())

php_mt_srand(GENERATE_SEED());

已知state生成的关键点在于seed( = GENERATESEED()) 这儿主要需要证明, 先后调用GENERATESEED(),获取的值是一样的:# php_rand.h

#ifdef PHP_WIN32

#define GENERATE_SEED() (((zend_long) (time(0) * GetCurrentProcessId())) ^ ((zend_long) (1000000.0 * php_combined_lcg())))

#else

#define GENERATE_SEED() (((zend_long) (time(0) * getpid())) ^ ((zend_long) (1000000.0 * php_combined_lcg())))

#endif

根据源码可以得出:

1.GENERATESEED()的数据类型为zendlong,zendlong的范围为uint32t

2.其生成取决于phpcombinedlcg()和 [GetCurrentProcessId()或getpid()],当在一个进程下, 先后调用[GetCurrentProcessId()或getpid()],的值是一样,那么只需要关注一下phpcombinedlcg:

lcg.c

根据代码可以很明显的知道, 第一次调用phpcombinedlcg,会播种生成了新的s1和s2,第二次再调用,不再播种, 用的先前的s1和s2,那么phpcombinedlcg是相等的。

所以先后调用GENERATE_SEED, 值是一样的。

3.5 抽象理解:

由于能力有限并没有具体去看state和BG的数据结构,上面分析可能存在问题, 但基于上面的分析, 可以做如下的抽象理解:

mt_srand用seed构造出来一个叫做state的东西, 可以看成是数组结构, 然后BG可以看成一个字典结构,用JSON格式表示一下:BG = {

"next": [a,b,c,d] , # new_state

"left": N , # 记录next里面剩余数量

}

那么:函数mt_initialize == 使用seed生成一个新的state

函数mtrealod == 将state做了一些函数变化得到newstate, 然后一个赋值到 BG["next"]

函数mtsrand == mtinitialize+mt_realod+标记已经播种

函数mtrand == BG["next"].pop(0) , 取出newstate里面第一个

4. 结论

4.1 影响随机数生成的因素为两个: 1. 种子 2. 次数 (3.5)4.2 srand/mtsrand相当于重置了次数,rand/mtrand相当于次数+=1 (3.1, 3.2)4.3 PHP5下rand/srand和mtrand/mtsrand是独立的,种子和次数均不相互干扰, 在同seed,同次数下,值不一样 (1.1, 1.2)4.2 PHP7下rand/srand和mtrand/mtsrand的种子和次数均互相干扰, 在同seed,同次数下,值完全一样(可以看成同一个函数,会舒服一些) (2.2)4.3 PHP5的rand/srand和PHP5的mtrand/mtsrand和PHP7的rand/srand/mtrand/mtsrand,在同seed,同次数下,值不一样 (1.1, 1.2, 2.1)4.4 种子区间为0到0xffffffff, 且有如下等式 (3.4)mt_srand(4294967297); == mt_srand(1) == mt_srand(-4294967295);

mt_srand(-4294967297); == mt_srand(-1) == mt_srand(4294967295);

srand(4294967297); == srand(1) == srand(-4294967295);

4.6 同一进程下,先后被调用的rand和mt_rand, 在未播种的前提下, 会使用同一个随机种子 (3.3)

四、其他

PYTHON和PHP随机函数是否相同?

需要根据PHP的代码, 用C去实现,python自带的rand和php的存在区别:)

五、参考

*本文作者:光通天下无患实验室  Djerryz,转载请注明来自FreeBuf.COM

php+伪随机算法,DEDECMS伪随机漏洞分析 (一) :PHP下随机函数的研究相关推荐

  1. 【算法】随机算法和双随机的实现思路

    前言 在产品需求中,比如抽奖,配对,会用到随机的概念 ,对应到功能实现中,也就是对应的随机算法. 单随机 需求 比如做一个简单的抽奖轮盘,每次抽奖,随机出一个结果,由前端展示抽奖结果. 每个奖项都有对 ...

  2. python 加权随机算法_加权随机算法 - 飞儿飞的个人空间 - OSCHINA - 中文开源技术交流社区...

    加权随机算法一般应用在以下场景:有一个集合S,里面比如有A,B,C,D这四项.这时我们想随机从中抽取一项,但是抽取的概率不同,比如我们希望抽到A的概率是50%,抽到B和C的概率是20%,D的概率是10 ...

  3. c语言微信抢红包的随机算法,微信红包随机算法是什么?

    现在微信上面最受欢迎的一项功能莫过于微信红包了,不知道大家有没有研究过,这个红包的数值是随机的,有的时候自己是运气王,有的时候手气特别的差,下面小编为大家介绍微信红包随机算法. 算法很简单,不是提前算 ...

  4. 众妙之门玄之又玄,游戏系统中的伪随机(Pseudo-Randomization)和真随机(True-Randomization)算法实现Python3

    原文转载自「刘悦的技术博客」https://v3u.cn/a_id_212 有人说,如果一个人相信运气,那么他一定参透了人生.想象一下,如果你在某款moba游戏中,在装备平平,队友天坑的情况下,却刀刀 ...

  5. python 加权随机算法_python的random模块及加权随机算法的python实现方法

    random是用于生成随机数的,我们可以利用它随机生成数字或者选择字符串. •random.seed(x)改变随机数生成器的种子seed. 一般不必特别去设定seed,Python会自动选择seed. ...

  6. 算法设计技巧与分析(八):随机算法(Randomized Algorithms)

    文章目录 随机算法(Randomized Algorithms) 一.随机选择(Randomized Selection) 二.测试字符串相等性(Testing String Equality) 三. ...

  7. 游戏中常用的伪随机算法之PRD暴击算法

    游戏中常用的伪随机算法之PRD暴击算法 PRD伪随机算法常用于游戏中的暴击算法,因此本文的标题将其称为 PRD暴击算法. 诞生与应用 PRD算法诞生与<魔兽争霸3>,可以说其诞生就是为了解 ...

  8. java random 伪随机_真/伪随机、以及随机算法

    伪随机性(英语:Pseudorandomness)是一个过程似乎是随机的,但实际上并不是.伪随机数是看似随机实质是固定的周期性序列,也就是有规则的随机. 什么是随机数 随机数在计算机应用中使用的比较广 ...

  9. 伪随机算法c语言,伪随机算法实现各语言实现示例。

    该楼层疑似违规已被系统折叠 隐藏此楼查看此楼 无聊,又研究了一下几种排序算法,在测速的时候,发现自己忘记了一个重要的问题,在某天看到有人在帖吧提到生成随机数只计数到32768就停止了,顺手查了一下C库 ...

最新文章

  1. MongoDB readConcern 原理解析
  2. 利用ArcMap对tiff或jpg格式地图图片的配准步骤
  3. editplus行转列_EditPlus常用快捷键
  4. 如何安装Gradle
  5. java的选项板_CAD工具选项板的介绍以及新建方法
  6. [react] React的displayName有什么作用?
  7. Apusic Operamasks的资源注入
  8. cupsd进程_linux pstree命令显示正在运行的进程的进程树状图
  9. 在STM8单片机中自己实现 printf()函数功能
  10. mysql怎么分读写_MYSQL的读写分离
  11. LINUX搭建EtherPad环境
  12. C# string byte数组互转;string byte[]互转
  13. php解密抖音小程序用户手机号/字节跳动小程序thinkphp
  14. lae界面开发工具入门介绍之一新建工程篇
  15. “隐藏高手” 胰腺癌的新出路——微生物
  16. 第八章-数据处理的两个基本问题
  17. nodejs-指定长度断句
  18. 如何用python打印三角阵列_如何打印完整的NumPy阵列?
  19. 使用Travis-CI自动部署博客
  20. 自动驾驶传感器产业链

热门文章

  1. 基于微信小程序的旅游网站
  2. ROS wiki learn 整理 1
  3. 【Django | allauth】重写allauth重置密码方法
  4. 音频声学基础三,人耳听觉特性
  5. 西工大2021夏信息技术基础认知与实践Python方向作业day0102
  6. 【操作系统】Oranges学习笔记(五) 第六章 进程
  7. 如何恢复三星手机SD卡数据
  8. 海康/大华SDK视频智能分析安防监控系统EasyCVR集成iframe播放分屏出现滚动条原因排查
  9. plm,tc(teamCenter)学习笔记
  10. “双11”狂欢将至,这一次,区块链会成为打假的终极利器吗?