php伪随机数安全

本文探讨了PHP中的随机数生成函数rand()和mt_rand()的安全问题,特别是mt_rand()的固定种子可能导致的不安全性。通过分析,指出攻击者可能通过获取系统时间来枚举种子,从而预测随机数序列。文章还提到了CTF题目的相关场景,并介绍了如何通过工具寻找种子,以及种子固定可能引发的安全风险,如重置密码链接生成等。
摘要由CSDN通过智能技术生成

随机数真的随机吗?

PHP中的随机函数

在PHP中,常用的随机数生成算法有rand(),mt_rand().

这两个函数各有最大范围不超过2147483647,rand()的范围是很小的,非常不安全的,所以一般用mt_rand().

<?php
//on windows
print getrandmax();//2147483647
print mt_getrandmax();//2147483647
?>

然鹅mt_rand()在实现上也有缺陷.

伪随机数是由数学算法来实现的,真正随机的地方在于种子.种子一旦确定,再通过同一随机数算法计算出来的随机数,值是固定的.多次计算所得值得顺序也是固定的

在PHP4.2.0之前的版本,必须要通过srand()或mt_srand()给rand()或mt_rand()播种,

在PHP4.2.0之后的版本,事先可以不再通过srand()或mt_srand()播种. 如直接调用mt_rand(),系统会自动播种.

但是,可能为了和之前版本兼容,PHP代码里面还会这样写:

mt_srand(time());
mt_srand((double) microtime() * 100000);
mt_srand((double) microtime() * 1000000);
mt_srand((double) microtime() * 10000000);

但是,时间也不是随机的 . 攻击者通过某种方式获取系统时间,就可以短时间内枚举出种子

上面提到的如果不播种,系统会自动播种,系统播种种子范围为0-2^32(32位系统),这样似乎也能枚举emm

固定的种子

下面谈谈种子固定会发生什么?

**在同一进程中,同一个seed,每次通过mt_rand()生成的值都是固定的: **

rand.php:

<?php
mt_srand(1);
echo mt_rand().'<br/>';
echo mt_rand().'<br/>';
echo mt_rand().'<br/>';
echo mt_rand().'<br/>';
echo mt_rand().'<br/>';
echo mt_rand().'<br/>';
?>

无论访问这个页面多少次,都是上面的结果,上面的序列.正好验证了上面的结论;

得到相同的种子

这里有个trick是,可以通过Keep-Alive HTTP头,迫使服务端使用同一PHP进程相应请求,所以也就能使种子保持一直.

别的就依赖PHP程序员出错了.

获得种子

既然知道了,同一个种子生成的序列是固定的,那么也能根据序列猜测seed

工具:php_mt_seed:https://github.com/lepiaf/php_mt_seed
Linux下安装使用方法

git clone https://github.com/lepiaf/php_mt_seed 
cd php_mt_seed/
gcc php_mt_seed.c -o php_mt_seed
make

使用: ./php_mt_seed 随机数

就会根据随机数,找seed,可能会找到多个,就需要自己验证哪个seed符和条件了

CTF题目

题目来自@https://ctf.show/

0x01

<?php

/*
# -*- coding: utf-8 -*-
# @Author: h1xa
# @Date:   2020-09-03 13:26:39
# @Last Modified by:   h1xa
# @Last Modified time: 2020-09-03 13:53:31
# @email: h1xa@ctfer.com
# @link: https://ctfer.com

*/

error_reporting(0);
include("flag.php");
if(isset($_GET['r'])){
    $r = $_GET['r'];
    mt_srand(372619038);
    if(intval($r)===intval(mt_rand())){
        echo $flag;
    }
}else{
    highlight_file(__FILE__);
    echo system('cat /proc/version');
}
 mt_srand(372619038);
 var_dump(mt_rand());//int(1155388967)

0x02

<?php

/*
# -*- coding: utf-8 -*-
# @Author: h1xa
# @Date:   2020-09-03 13:56:57
# @Last Modified by:   h1xa
# @Last Modified time: 2020-09-03 15:47:33
# @email: h1xa@ctfer.com
# @link: https://ctfer.com

*/


error_reporting(0);
include("flag.php");
if(isset($_GET['r'])){
    $r = $_GET['r'];
    mt_srand(hexdec(substr(md5($flag), 0,8)));
    $rand = intval($r)-intval(mt_rand());
    if((!$rand)){
        if($_COOKIE['token']==(mt_rand()+mt_rand())){
            echo $flag;
        }
    }else{
        echo $rand;
    }
}else{
    highlight_file(__FILE__);
    echo system('cat /proc/version');
}

由?r=1

可以算出序列中第一个数,再跑脚本

找到两个种子,一个一个试

可以利用插件改cookie

利用场景

重置密码的链接生成.
欢迎补充

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值