php+伪随机算法,DEDECMS伪随机漏洞分析 (一) :PHP下随机函数的研究
一 、开篇
在某次复现"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下随机函数的研究相关推荐
- 【算法】随机算法和双随机的实现思路
前言 在产品需求中,比如抽奖,配对,会用到随机的概念 ,对应到功能实现中,也就是对应的随机算法. 单随机 需求 比如做一个简单的抽奖轮盘,每次抽奖,随机出一个结果,由前端展示抽奖结果. 每个奖项都有对 ...
- python 加权随机算法_加权随机算法 - 飞儿飞的个人空间 - OSCHINA - 中文开源技术交流社区...
加权随机算法一般应用在以下场景:有一个集合S,里面比如有A,B,C,D这四项.这时我们想随机从中抽取一项,但是抽取的概率不同,比如我们希望抽到A的概率是50%,抽到B和C的概率是20%,D的概率是10 ...
- c语言微信抢红包的随机算法,微信红包随机算法是什么?
现在微信上面最受欢迎的一项功能莫过于微信红包了,不知道大家有没有研究过,这个红包的数值是随机的,有的时候自己是运气王,有的时候手气特别的差,下面小编为大家介绍微信红包随机算法. 算法很简单,不是提前算 ...
- 众妙之门玄之又玄,游戏系统中的伪随机(Pseudo-Randomization)和真随机(True-Randomization)算法实现Python3
原文转载自「刘悦的技术博客」https://v3u.cn/a_id_212 有人说,如果一个人相信运气,那么他一定参透了人生.想象一下,如果你在某款moba游戏中,在装备平平,队友天坑的情况下,却刀刀 ...
- python 加权随机算法_python的random模块及加权随机算法的python实现方法
random是用于生成随机数的,我们可以利用它随机生成数字或者选择字符串. •random.seed(x)改变随机数生成器的种子seed. 一般不必特别去设定seed,Python会自动选择seed. ...
- 算法设计技巧与分析(八):随机算法(Randomized Algorithms)
文章目录 随机算法(Randomized Algorithms) 一.随机选择(Randomized Selection) 二.测试字符串相等性(Testing String Equality) 三. ...
- 游戏中常用的伪随机算法之PRD暴击算法
游戏中常用的伪随机算法之PRD暴击算法 PRD伪随机算法常用于游戏中的暴击算法,因此本文的标题将其称为 PRD暴击算法. 诞生与应用 PRD算法诞生与<魔兽争霸3>,可以说其诞生就是为了解 ...
- java random 伪随机_真/伪随机、以及随机算法
伪随机性(英语:Pseudorandomness)是一个过程似乎是随机的,但实际上并不是.伪随机数是看似随机实质是固定的周期性序列,也就是有规则的随机. 什么是随机数 随机数在计算机应用中使用的比较广 ...
- 伪随机算法c语言,伪随机算法实现各语言实现示例。
该楼层疑似违规已被系统折叠 隐藏此楼查看此楼 无聊,又研究了一下几种排序算法,在测速的时候,发现自己忘记了一个重要的问题,在某天看到有人在帖吧提到生成随机数只计数到32768就停止了,顺手查了一下C库 ...
最新文章
- MongoDB readConcern 原理解析
- 利用ArcMap对tiff或jpg格式地图图片的配准步骤
- editplus行转列_EditPlus常用快捷键
- 如何安装Gradle
- java的选项板_CAD工具选项板的介绍以及新建方法
- [react] React的displayName有什么作用?
- Apusic Operamasks的资源注入
- cupsd进程_linux pstree命令显示正在运行的进程的进程树状图
- 在STM8单片机中自己实现 printf()函数功能
- mysql怎么分读写_MYSQL的读写分离
- LINUX搭建EtherPad环境
- C# string byte数组互转;string byte[]互转
- php解密抖音小程序用户手机号/字节跳动小程序thinkphp
- lae界面开发工具入门介绍之一新建工程篇
- “隐藏高手” 胰腺癌的新出路——微生物
- 第八章-数据处理的两个基本问题
- nodejs-指定长度断句
- 如何用python打印三角阵列_如何打印完整的NumPy阵列?
- 使用Travis-CI自动部署博客
- 自动驾驶传感器产业链
热门文章
- 基于微信小程序的旅游网站
- ROS wiki learn 整理 1
- 【Django | allauth】重写allauth重置密码方法
- 音频声学基础三,人耳听觉特性
- 西工大2021夏信息技术基础认知与实践Python方向作业day0102
- 【操作系统】Oranges学习笔记(五) 第六章 进程
- 如何恢复三星手机SD卡数据
- 海康/大华SDK视频智能分析安防监控系统EasyCVR集成iframe播放分屏出现滚动条原因排查
- plm,tc(teamCenter)学习笔记
- “双11”狂欢将至,这一次,区块链会成为打假的终极利器吗?