CTF_Web:php伪随机数mt_rand()函数+php_mt_seed工具使用
CTF_Web:php伪随机数mt_rand函数漏洞
0x00 问题描述
最近在题目练习的时候遇到了一个伪随机数的例子,刚好丰富一下php类型的考点梳理,主要涉及mt_rand()函数、php_mt_seed种子爆破工具的使用等内容。
0x01 mt_rand函数
mt_rand()
函数
mt_rand() 函数使用 Mersenne Twister 算法生成随机整数。
使用语法:mt_rand(); or mt_rand(min,max);,生成一个区间内的随机数。
其参数min
默认为最小值0
,max
默认为可生成的随机数最大值2147483647
,由mt_getrandmax()
函数获得。
mt_srand()
函数
mt_srand() 函数播种 Mersenne Twister 随机数生成器。
提示:从 PHP 4.2.0 开始,随机数生成器自动播种,因此没有必要使用该函数。当不使用随机数播种函数srand时,php也会自动为随机数播种,因此是否确定种子都不会影响正常运行。
在php中每一次调用mt_rand()函数,都会检查一下系统有没有播种。(播种为mt_srand()函数完成),当随机种子生成后,后面生成的随机数都会根据这个随机种子生成。所以同一个种子下,随机数的序列是相同的,这就是漏洞点,我们先看两个例子。
mt_srand(0);echo mt_rand();echo mt_rand();echo mt_rand();?>
在上面的代码中,我们把随机数播种为0,每次运行都会获得相同的序列,这就是伪随机:
96393219212731241191535857466
当我们去掉mt_srand()函数时,再次重复运行实例,系统会自动为rand函数播种,但也是播种一次。因此多次重复运行的结果也相同,为:
9929788299287481011380702626
因此在知晓一串随机序列的条件下,基于序列相同的seed爆破就是可能实现的。
0x02 CTF例题
include 'flag.php';session_start();$_SESSION['seed'] = rand(0,999999999);function genStr($length, $sc = FALSE) { mt_srand($_SESSION['seed']); $rand_string = "abcdefghijklmnopqrstuvwxyz0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"; $retStr = ''; for ( $i = 0; $i < $length; $i++ ){ $retStr .= substr($rand_string,mt_rand(0, strlen($rand_string) - 1), 1); } if ($sc === TRUE) { setcookie('key_is', $retStr); } return $retStr;}if (!isset($_SESSION['flag'])) { $key = genStr(16, TRUE); $_SESSION['flag'] = genStr(32);}if (strlen($_GET['key']) == 32) { if ($_GET['key'] === $_SESSION['flag']) { echo $FLAGG; //这里输出flag }else{ echo "咋回事,位数对了,key值不对啊,你别想忽悠我啊!\n"; }}else { echo "亲,我要32位的key,你的key不等于32位噢!\n";}if ($_GET['showcode'] == 1) { highlight_file(__FILE__);}?>
通过上面的代码可以发现,首先使用rand(0,999999999);
函数确认种子,再通过生成的随机数序列在$rand_string
中确认key值的内容。且key
与flag
的生成均使用了同一个mt_srand()
播种。并将16位的key
值通过cookie
传递。
因此16位序列是我们所已知的,通过F12工具抓包查看key值:
key = GgEAeCi3GWROTQXg
至此题目源码分析完毕,只需使用 php_mt_seed
工具得到seed
值,再次生成对应的32位flag
即可。
0x03 php_mt_seed工具使用
php_mt_seed
是c语言编写的爆破随机数序列种子的工具。其项目官网为:https://www.openwall.com/php_mt_seed/
github地址为:https://github.com/openwall/php_mt_seed
点击下载后,在shell中运行make命令。
程序编译完成后,使用官方文档中的使用方法:
$allowable_characters = 'abcdefghijklmnopqrstuvwxyz0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ'; $len = strlen($allowable_characters) - 1; $pass = $argv[1]; for ($i = 0; $i < strlen($pass); $i++) { $number = strpos($allowable_characters, $pass[$i]); echo "$number $number 0 $len "; } echo "\n"; ?>
将我们的序列转换为 php_mt_seed
可以识别的格式。
然后使用
./php_mt_rand 42 42 0 61 6 6 0 61 40 40 0 61 36 36 0 61 4 4 0 61 38 38 0 61 8 8 0 61 29 29 0 61 42 42 0 61 58 58 0 61 53 53 0 61 50 50 0 61 55 55 0 61 52 52 0 61 59 59 0 61 6 6 0 61
命令获得种子。 seed=368872094
最后将种子代入生成key的函数中验证。
$seed = 368872094; mt_srand($seed); $rand_string = "abcdefghijklmnopqrstuvwxyz0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"; $retStr = ''; for ( $i = 0; $i < 32; $i++ ){ $retStr .= substr($rand_string,mt_rand(0, strlen($rand_string) - 1), 1); } echo $retStr;?> //GgEAeCi3GWROTQXgEhr2jfxIDSZequqG
结果为:
key = GgEAeCi3GWROTQXg
flag = GgEAeCi3GWROTQXgEhr2jfxIDSZequqG
与我们所分析的结果相同,成功获得flag。
0x04 参考文章
来源地址:https://blog.csdn.net/qq_35493457/article/details/124080444
免责声明:
① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。
② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341