這期內(nèi)容當(dāng)中小編將會給大家?guī)碛嘘P(guān)如何理解PHP中的隨機(jī)數(shù)安全問題,文章內(nèi)容豐富且以專業(yè)的角度為大家分析和敘述,閱讀完這篇文章希望大家可以有所收獲。
成都創(chuàng)新互聯(lián)主營龍川網(wǎng)站建設(shè)的網(wǎng)絡(luò)公司,主營網(wǎng)站建設(shè)方案,成都app開發(fā),龍川h5成都小程序開發(fā)搭建,龍川網(wǎng)站營銷推廣歡迎龍川等地區(qū)企業(yè)咨詢
1、引言
西湖論劍杯線上預(yù)選賽線上賭場一題,明文攻擊出來的hint中給了/flag/seed.txt以及一個(gè)字符串code,這里需要稍微腦洞一點(diǎn)想到seed是指隨機(jī)數(shù)種子,以及Web頁面上的code值是每小時(shí)更換的"隨機(jī)數(shù)":
我們利用phpmtseed工具(C編寫,速度很快)可以根據(jù)隨機(jī)數(shù)碰撞出隨機(jī)數(shù)的種子,從而獲取flag:
以下是原理分析:
2、隨機(jī)數(shù)的安全缺陷
隨機(jī)數(shù)廣泛應(yīng)用于生成驗(yàn)證碼、Token、密鑰等場景中,分為真隨機(jī)數(shù)和偽隨機(jī)數(shù)。我們通過算法(常用線性同余)和種子(常用時(shí)鐘)得到的隨機(jī)數(shù)屬于偽隨機(jī)數(shù):當(dāng)知道種子或已產(chǎn)生的隨機(jī)數(shù)時(shí),隨機(jī)數(shù)序列是可以被預(yù)測的。
可以看到PHP Manual其實(shí)提示了生成隨機(jī)數(shù)用于加密是不安全的,但是這個(gè)Caution不知為何只存在于英文版的PHP Manual中,中文版被遺漏了...這可能也是很多國內(nèi)的開發(fā)應(yīng)用出現(xiàn)過此缺陷的一個(gè)原因。
PHP中生成隨機(jī)數(shù)的函數(shù)有rand()和mtrand(),它們分別對應(yīng)srand()和mtstrand()兩個(gè)用于播種隨機(jī)數(shù)種子的函數(shù)。我們建立rand.php進(jìn)行測試:
<?php
mt_srand(2333);
srand(2333);
echo "seed=2333,rand()產(chǎn)生的隨機(jī)數(shù)序列:\n";
for($i=1;$i<=3;$i++){
echo rand()."\n";
}
echo "seed=2333,mt_rand()產(chǎn)生的隨機(jī)數(shù)序列:\n";
for($i=1;$i<=3;$i++){
echo mt_rand()."\n";
}
?>
執(zhí)行:
可以看出當(dāng)隨機(jī)數(shù)種子相同時(shí),不管是rand()還是mtrand()產(chǎn)生的隨機(jī)數(shù)序列都是相同的,如果seed泄露則會導(dǎo)致隨機(jī)數(shù)序列的泄露。當(dāng)種子值為固定如mtsrand(1000)時(shí),隨機(jī)數(shù)形同虛設(shè);而使用動(dòng)態(tài)種子也未必安全,如:
//seed值較小,直接遍歷爆破
mt_srand(mt_rand(0,1000));
//用公開的time()作為種子,和靜態(tài)種子一樣危險(xiǎn)
mt_srand(time());
//破解時(shí)要注意服務(wù)器時(shí)間可能存在偏差,需要設(shè)定一個(gè)較小的范圍
自PHP 4.2.0 起,隨機(jī)數(shù)發(fā)生器會自動(dòng)完成播種,不再需要手工調(diào)用srand()或mt_srand(),但是這樣仍舊不安全,我們分別對兩個(gè)函數(shù)進(jìn)行討論
3、rand()
rand()在產(chǎn)生隨機(jī)數(shù)時(shí)不會自動(dòng)調(diào)用srand(),產(chǎn)生的隨機(jī)數(shù)序列可以通過這個(gè)式子預(yù)測:
state[i] = state[i-3] + state[i-31]
所以我們可以收集rand()生成的32位以上的隨機(jī)序列,以預(yù)測后面的隨機(jī)序列。
詳細(xì)參考:Cracking-Php-Rand
(http://www.sjoerdlangkemper.nl/2016/02/11/cracking-php-rand/)
并且在某些平臺下rand()最大值為32767,非常容易遭到爆破。
4、mt_rand()
根據(jù)PHP Manual,mtrand()產(chǎn)生隨機(jī)數(shù)值的平均速度比libc提供的rand()快四倍,rand() 函數(shù)默認(rèn)使用 libc 隨機(jī)數(shù)發(fā)生器,mtrand() 函數(shù)是非正式用來替換它的。
mtrand()函數(shù)的安全缺陷主要出現(xiàn)在,所謂"自動(dòng)播種"其實(shí)是PHP在同一個(gè)請求進(jìn)程中只會進(jìn)行一次播種,也就是說即使多次調(diào)用mtrand()函數(shù),也只會根據(jù)第一次播種的種子生成隨機(jī)數(shù)。這一結(jié)論的證明可以通過mt_rand()的源碼分析或?qū)憘€(gè)小腳本測試來完成,不再展開,函數(shù)的核心實(shí)現(xiàn)代碼是這一部分:
PHPAPI void php_mt_srand(uint32_t seed)
{
/* Seed the generator with a simple uint32 */
php_mt_initialize(seed, BG(state));
php_mt_reload();
/* Seed only once */
BG(mt_rand_is_seeded) = 1;
}
/* }}} */
/* {{{ php_mt_rand
*/
PHPAPI uint32_t php_mt_rand(void)
{
/* Pull a 32-bit integer from the generator state
Every other access function simply transforms the numbers extracted here */
register uint32_t s1;
if (UNEXPECTED(!BG(mt_rand_is_seeded))) {
php_mt_srand(GENERATE_SEED());
}
if (BG(left) == 0) {
php_mt_reload();
}
--BG(left);
s1 = *BG(next)++;
s1 ^= (s1 >> 11);
s1 ^= (s1 << 7) & 0x9d2c5680U;
s1 ^= (s1 << 15) & 0xefc60000U;
return ( s1 ^ (s1 >> 18) );
}
由于根據(jù)種子生成隨機(jī)數(shù)序列的計(jì)算并不可逆,有效的破解方法應(yīng)該是窮舉種子并生成隨機(jī)數(shù)序列,與已知的隨機(jī)數(shù)(序列)作比較,這也是文章開頭提到的phpmtseed工具的實(shí)現(xiàn)邏輯。
5、安全建議
涉及到加密/權(quán)限/CSRF Token等敏感操作時(shí):
不要使用時(shí)間函數(shù)作為種子或直接作為隨機(jī)數(shù):time()/microtime()
不要直接使用rand()``mt_rand()這樣的弱偽隨機(jī)數(shù)生成器
隨機(jī)數(shù)要足夠長以防御暴力破解
上述就是小編為大家分享的如何理解PHP中的隨機(jī)數(shù)安全問題了,如果剛好有類似的疑惑,不妨參照上述分析進(jìn)行理解。如果想知道更多相關(guān)知識,歡迎關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道。
網(wǎng)站標(biāo)題:如何理解PHP中的隨機(jī)數(shù)安全問題
URL地址:http://jinyejixie.com/article48/posoep.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供網(wǎng)站策劃、響應(yīng)式網(wǎng)站、移動(dòng)網(wǎng)站建設(shè)、網(wǎng)頁設(shè)計(jì)公司、品牌網(wǎng)站制作、全網(wǎng)營銷推廣
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來源: 創(chuàng)新互聯(lián)