mt_rand伪随机数爆破

mt_rand伪随机数爆破

前置知识

mt_rand用法:

mt_rand()

mt_rand(min,max)

PHP mt_rand安全杂谈及应用场景详解 - FreeBuf网络安全行业门户

CTF| web篇之伪随机数 - FreeBuf网络安全行业门户

伪随机数安全问题

爆破出种子后,随机数可预测,导致加密不安全

爆破工具php_mt_seed

工具来源:

https://github.com/openwall/php_mt_seed.git

使用方法:

  • php_mt_seed expects 1, 2, 4, or more numbers on its command line. The

    numbers specify constraints on mt_rand() outputs.

  1. When invoked with only 1 number, that's the first mt_rand() output to
    find seeds for.

  2. When invoked with 2 numbers, those are the bounds (minimum and maximum,
    in that order) that the first mt_rand() output should fall within.

  3. When invoked with 4 numbers, the first 2 give the bounds for the first
    mt_rand() output and the second 2 give the range passed into mt_rand().

  4. When invoked with 5 or more numbers, each group of 4 and then the last
    group of 1, 2, or (usually) 4 are processed as above, where each group
    refers to a corresponding mt_rand() output.

可预测性验证:

用例1:

image-20240521203926287

扔到php_mt_seed中进行爆破,看对应的版本拿所需的seed

image-20240521204047884

可以看出知道种子后随机的结果就可以预测出来了

image-20240521203955579

其他用例

而对于其他用例,可以看回这篇文章中的随机验证码还原后爆破,那里使用了用例4的方式

PHP mt_rand安全杂谈及应用场景详解 - FreeBuf网络安全行业门户

CTF例题

[GWCTF 2019]枯燥的抽奖

通过查看网页源码后发现是通过check.php返回的值来判断是否给flag。

check.php源码

waZCyrr25g

<?php
#这不是抽奖程序的源代码!不许看!
header("Content-Type: text/html;charset=utf-8");
session_start();
if(!isset($_SESSION['seed'])){
$_SESSION['seed']=rand(0,999999999);
}

mt_srand($_SESSION['seed']);
$str_long1 = "abcdefghijklmnopqrstuvwxyz0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
$str='';
$len1=20;
for ( $i = 0; $i < $len1; $i++ ){
    $str.=substr($str_long1, mt_rand(0, strlen($str_long1) - 1), 1);       
}
$str_show = substr($str, 0, 10);
echo "<p id='p1'>".$str_show."</p>";


if(isset($_POST['num'])){
    if($_POST['num']===$str){x
        echo "<p id=flag>抽奖,就是那么枯燥且无味,给你flag{xxxxxxxxx}</p>";
    }
    else{
        echo "<p id=flag>没抽中哦,再试试吧</p>";
    }
}
show_source("check.php");

给到的 waZCyrr25g$str的前10位,我们需要猜出来完整的$str才能得到flag。$str$str_long1中每次截取1位,而且此位取自第mt_rand(0,len)位,最后组成20位的字符串

还原出随机数

<?php

$str_long1 = "abcdefghijklmnopqrstuvwxyz0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
$str='waZCyrr25g';
$seed='';
for($i=0;$i<strlen($str);$i++){
    $seed=strpos($str_long1,$str[$i]);
    echo $seed.' ';
}


//结果:22 0 61 38 24 17 17 28 31 6
//但是这些随机数是多次随机出来的结果,所以要转化为符合爆破脚本的格式
//即用例4:前两个数字输入随机数的边界(不理解,但是感觉对整数来说是它本身,小数来说是上下取证),后两个数字输入随机数的范围

php_mt_seed格式

<?php

$str_long1 = "abcdefghijklmnopqrstuvwxyz0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
$str='waZCyrr25g';
$seed='';
for($i=0;$i<strlen($str);$i++){
    $seed=strpos($str_long1,$str[$i]);
    echo $seed.' '.$seed.' 0 61 ';
}
//结果:
//22 22 0 61 0 0 0 61 61 61 0 61 38 38 0 61 24 24 0 61 17 17 0 61 17 17 0 61 28 28 0 61 31 31 0 61 6 6 0 61 

seed爆破

image-20240521212552361

seed是750772741 ,然后放回去check.php中计算出$str完整的值,提交$str即可获得flag

posted @ 2024-05-21 21:29  eth258  阅读(2)  评论(0编辑  收藏  举报