溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

php隨機(jī)函數(shù)mt_rand()產(chǎn)生的小問題大漏洞

發(fā)布時間:2020-06-28 04:43:54 來源:網(wǎng)絡(luò) 閱讀:4843 作者:菜鵝小生 欄目:安全技術(shù)

**說到隨機(jī)函數(shù)的應(yīng)用,作為一個菜鳥,理解的也不是很深刻,在這里之作為一個筆記來記錄,以后慢慢將其掌握之后,再在內(nèi)容上面進(jìn)行加深。

隨機(jī)函數(shù)的作用,常常是用來生成驗證碼、隨機(jī)文件名、訂單號,如果用來做安全驗證的話常常用來生成加密key、token等等。**

一、常見的隨機(jī)函數(shù)

1、rand()
常用的隨機(jī)函數(shù),默認(rèn)生成0-getrandmax()之間的隨機(jī)數(shù),不過因為性能問題,已經(jīng)被mt_rand()函數(shù)替代
相關(guān)函數(shù):
rand(int $min,int $max)
srand(int $seed),生成時間種子,同一個時間種子下隨機(jī)生成的隨機(jī)數(shù)值是相同的。
getrandmax()獲取最大隨機(jī)數(shù),這里獲取的隨機(jī)數(shù)會隨系統(tǒng)的不同而不同。如linux最大2147483647
2、mt_rand
常用的隨機(jī)函數(shù),默認(rèn)生成0-mt_getrandmax()之間的隨機(jī)數(shù),?Mersenne Twister 算法生成隨機(jī)整數(shù)
相關(guān)函數(shù):
mt_srand(),生成種子,同一個種子下隨機(jī)生成的隨機(jī)數(shù)值是相同的。
該函數(shù)是產(chǎn)生隨機(jī)值的更好選擇,返回結(jié)果的速度是?rand()?函數(shù)的 4 倍(手冊是是這么寫的),我個人并不認(rèn)同的,我感覺他說的4倍是很多年前的事了。因為mt_rand()使用的Mersenne Twister algorythm是1997的事,所以在很多年前,和rand()在速度上的差異可能是(4倍),自2004年,rand()已經(jīng)開始使用algorythm,所以現(xiàn)在它們速度上沒有太大的區(qū)別.
有時候手冊也是騙人的,就像一會要說的這個函數(shù)造成的問題。
3、uniqid()
生成唯一ID的函數(shù),精確到了微妙,較mt_rand精確。適用場景生成token和生成uuid
具體細(xì)節(jié)沒做研究
4、openssl_random_pseudo_bytes()
適用于生成token,具體詳情沒做研究

二、mt_rand()函數(shù)造成的問題所在

--
今天重點記錄一下mt_rand帶來的問題,和在CTF中的具體解法。對于這個函數(shù)的介紹是有兩個版本的,一個是英文版,一個是中文版,去對比一下,在英文版中會多出一個警告:

Caution:This function does not generate cryptographically secure values, and should not be used for cryptographic purposes. If you need a cryptographically secure value, consider using?random_int(),?random_bytes(), or?openssl_random_pseudo_bytes()?instead.

意思是注意函數(shù)的安全,不能用來生成密碼安全值,不要引用于加密,如果需要可以適用等等函數(shù)代替。其實函數(shù)本身是沒有問題的,只是使用的方式不當(dāng)而已。
我沒有挖漏洞的經(jīng)驗,所以也不清楚大佬說的這方面的漏洞多不多,但以我個人而言,肯定只會選擇看中文版的介紹,并且使用此函數(shù)去生成密碼安全值。這樣就不知道警告,也就會造成安全問題。

首先我們要知道,每一次調(diào)用mt_rand()函數(shù)的時候,都會檢查一下系統(tǒng)有沒有播種。(播種是由mt_srand()函數(shù)完成的),當(dāng)隨機(jī)種子生成后,后面生成的隨機(jī)數(shù)都會根據(jù)這個隨機(jī)種子生成。所以前面也說到,同一個種子下隨機(jī)生成的隨機(jī)數(shù)值是相同的。同時,也解釋了我們破解隨機(jī)種子的可行性。如果每次調(diào)用mt_rand()函數(shù)都需要生成一個隨機(jī)種子的話,那根本就沒辦法破解。
做一個簡單的測試,測試隨機(jī)數(shù)種子相同,后面的每次執(zhí)行的隨機(jī)數(shù)也相同
腳本:

<?php
mt_srand(45678913);
echo mt_rand()."<br/>";
echo mt_rand()."<br/>";
echo mt_rand()."<br/>";
echo mt_rand()."<br/>";
echo mt_rand()."<br/>";
echo mt_rand()."<br/>";
echo mt_rand()."<br/>";
echo mt_rand()."<br/>";
echo mt_rand()."<br/>";
?>

php隨機(jī)函數(shù)mt_rand()產(chǎn)生的小問題大漏洞
兩次執(zhí)行結(jié)果:
php隨機(jī)函數(shù)mt_rand()產(chǎn)生的小問題大漏洞
可以看到得到的隨機(jī)數(shù)是相同的。
同時我們應(yīng)該注意,mt_srand()函數(shù)播種的時候,只有在第一次調(diào)用mt_rand()函數(shù)的時候才會使用。所以如果我們知道了第一次生成的隨機(jī)數(shù)值,就可能爆破出隨機(jī)數(shù)種子。

--
接下來就來驗證一下
首先爆破出隨機(jī)數(shù)種子,利用工具php_mt_srand
工具鏈接:https://github.com/lepiaf/php_mt_seed
這個工具的具體用法,也不再著解釋,說起來還是挺復(fù)雜的,在這里推薦一個文章吧,看完就看一了解個大概,同時還有助于理解隨機(jī)數(shù)

https://×××w.openwall.com/php_mt_seed/README
爆破隨機(jī)數(shù)種子,我們將得到的第一組數(shù)進(jìn)行爆破
php隨機(jī)函數(shù)mt_rand()產(chǎn)生的小問題大漏洞
得到三組seed值,里面就有我們使用的隨機(jī)數(shù)種子,當(dāng)然在正常情況下我們是不知道這個數(shù)值的,所以還需要去驗證。

--
如何驗證?
1、只需要將這個種子通過mt_srand()函數(shù)生成數(shù)值后再調(diào)用幾組mt_rand()函數(shù)生成幾組隨機(jī)數(shù)\
2、然后將隨機(jī)數(shù)和我們剛開始得到的隨機(jī)數(shù)對比即可。
測試第一組
php隨機(jī)函數(shù)mt_rand()產(chǎn)生的小問題大漏洞

php隨機(jī)函數(shù)mt_rand()產(chǎn)生的小問題大漏洞
測試第二組
php隨機(jī)函數(shù)mt_rand()產(chǎn)生的小問題大漏洞

php隨機(jī)函數(shù)mt_rand()產(chǎn)生的小問題大漏洞
測試第三組
php隨機(jī)函數(shù)mt_rand()產(chǎn)生的小問題大漏洞

php隨機(jī)函數(shù)mt_rand()產(chǎn)生的小問題大漏洞
可以看到只有第二組的隨機(jī)數(shù)和原來的相同,到這里便成功獲取到了seed值。

三、CTF中的題目

題目來自于成都大學(xué)網(wǎng)絡(luò)***演練平臺--隨機(jī)數(shù)
題目鏈接:http://ctf.cdusec.org/challenges
題目非常簡單,直接就給出了題目隨機(jī)數(shù)的源碼以及前幾組隨機(jī)數(shù):

<?php
echo "PHP 5.4.26";
mt_srand(xxxxxxxx);
#We can't tell you what is xxxxxxxx!
echo mt_rand()."<br/>";
echo mt_rand()."<br/>";
echo mt_rand()."<br/>";
echo mt_rand()."<br/>";
echo mt_rand()."<br/>";
echo mt_rand()."<br/>";
echo mt_rand()."<br/>";
echo mt_rand()."<br/>";
echo mt_rand()."<br/>";
echo mt_rand()."<br/>";
echo "echo flag{".mt_rand()."}"
?>
984489752
619387123
2070958802
2105559368
1909473866
1679323715
1910332168
640569646
1103001695
1871111424
flag
So, Please guess the flag!

理解了上面所說的爆破步驟的話,對這個題目簡直太容易了。
1、因為我們不知道××××代表那些數(shù)字,但是給出了第一組隨機(jī)數(shù)。上面也說了,只有第一次調(diào)用mt_rand()函數(shù)的時候才會自動播種,接下來的就會根據(jù)這個種子生成隨機(jī)數(shù)。所以我們來利用第一組爆破
php隨機(jī)函數(shù)mt_rand()產(chǎn)生的小問題大漏洞
2、將seed數(shù)值帶入到腳本mt_srand()函數(shù)當(dāng)中,去跑flag,因為只要得到seed,接下來不管怎么跑,跑幾次,得到的幾組數(shù)值都是相同的。這里得到兩組seed值,測試兩次,將得到的flag遞交看一下那個正確即可。
php隨機(jī)函數(shù)mt_rand()產(chǎn)生的小問題大漏洞

四、應(yīng)當(dāng)注意的問題。

隨機(jī)數(shù)這個東西在系統(tǒng)之間和php版本之間是有削微的區(qū)別的,比如就CTF這道題目而言,開始我并沒有注意php版本問題,當(dāng)時的測試環(huán)境是php7的版本,同樣的做法,答案卻是不同的,所以結(jié)果也一直出不來。
同時也告訴我們,細(xì)節(jié)決定成敗。

因為是剛剛學(xué)習(xí)這一知識點,可能講解的也不夠詳細(xì)或者有些許錯誤。哪位大佬看到不準(zhǔn)確的希望給指出,謝謝!

相關(guān)鏈接:
http://php.net/manual/en/function.mt-rand.php
http://php.net/manual/zh/function.mt-rand.php

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI