亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 語言 > PHP > 正文

深入理解PHP中mt_rand()隨機數的安全

2024-05-05 00:00:27
字體:
來源:轉載
供稿:網友

前言

在前段時間挖了不少跟mt_rand()相關的安全漏洞,基本上都是錯誤理解隨機數用法導致的。這里又要提一下php/36097.html">php官網manual的一個坑,看下關于mt_rand()的介紹:中文版^cn 英文版^en,可以看到英文版多了一塊黃色的 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.

很多國內開發者估計都是看的中文版的介紹而在程序中使用了mt_rand()來生成安全令牌、核心加解密key等等導致嚴重的安全問題。

偽隨機數

mt_rand()并不是一個 真·隨機數 生成函數,實際上絕大多數編程語言中的隨機數函數生成的都都是偽隨機數。關于真隨機數和偽隨機數的區別這里不展開解釋,只需要簡單了解一點

偽隨機是由可確定的函數(常用線性同余),通過一個種子(常用時鐘),產生的偽隨機數。這意味著:如果知道了種子,或者已經產生的隨機數,都可能獲得接下來隨機數序列的信息(可預測性)。

簡單假設一下 mt_rand()內部生成隨機數的函數為: rand = seed+(i*10) 其中 seed 是隨機數種子, i 是第幾次調用這個隨機數函數。當我們同時知道 i 和 rand 兩個值的時候,就能很容易的算出seed的值來。比如 rand=21 , i=2 代入函數 21=seed+(2*10) 得到 seed=1 。是不是很簡單,當我們拿到seed之后,就能計算出當 i 為任意值時候的 rand 的值了。

PHP的自動播種

從上一節我們已經知道每一次mt_rand()被調用都會根據seed和當前調用的次數i來計算出一個偽隨機數。而且seed是自動播種的:

Note: 自 PHP 4.2.0 起,不再需要用 srand() 或 mt_srand() 給隨機數發生器播種 ,因為現在是由系統自動完成的。

那么問題就來了,到底系統自動完成播種是在什么時候,如果每次調用mt_rand()都會自動播種那么破解seed也就沒意義了。關于這一點manual并沒有給出詳細信息。網上找了一圈也沒靠譜的答案 只能去翻源碼^mtrand了:

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) );}

可以看到每次調用mt_rand()都會先檢查是否已經播種。如果已經播種就直接產生隨機數,否則調用php_mt_srand來播種。也就是說每個php cgi進程期間,只有第一次調用mt_rand()會自動播種。接下來都會根據這個第一次播種的種子來生成隨機數。而php的幾種運行模式中除了CGI(每個請求啟動一個cgi進程,請求結束后關閉。每次都要重新讀取php.ini 環境變量等導致效率低下,現在用的應該不多了)以外,基本都是一個進程處理完請求之后standby等待下一個,處理多個請求之后才會回收(超時也會回收)。

寫個腳本測試一下

<?php//pid.phpecho getmypid();
<?php//test.php$old_pid = file_get_contents('http://localhost/pid.php');$i=1;while(true){ $i++; $pid = file_get_contents('http://localhost/pid.php'); if($pid!=$old_pid){ echo $i; break; }}

測試結果:(windows+phpstudy)

apache 1000請求

nginx 500請求

當然這個測試僅僅確認了apache和nginx一個進程可以處理的請求數,再來驗證一下剛才關于自動播種的結論:

<?php//pid1.phpif(isset($_GET['rand'])){ echo mt_rand();}else{ echo getmypid();}
<?php//pid2.phpecho mt_rand();
<?php//test.php$old_pid = file_get_contents('http://localhost/pid1.php');echo "old_pid:{$old_pid}/r/n";while(true){ $pid = file_get_contents('http://localhost/pid1.php'); if($pid!=$old_pid){ echo "new_pid:{$pid}/r/n"; for($i=0;$i<20;$i++){  $random = mt_rand(1,2);  echo file_get_contents("http://localhost/pid".$random.".php?rand=1")." "; } break; }}

通過pid來判斷,當新進程開始的時候,隨機獲取兩個頁面其中一個的 mt_rand() 的輸出:

old_pid:972 new_pid:7752 1513334371 2014450250 1319669412 499559587 117728762 1465174656 1671827592 1703046841 464496438 1974338231 46646067 981271768 1070717272 571887250 922467166 606646473 134605134 857256637 1971727275 2104203195

拿第一個隨機數 1513334371 去爆破種子:

smldhz@vm:~/php_mt_seed-3.2$ ./php_mt_seed 1513334371 Found 0, trying 704643072 - 738197503, speed 28562751 seeds per second seed = 735487048 Found 1, trying 1308622848 - 1342177279, speed 28824291 seeds per second seed = 1337331453 Found 2, trying 3254779904 - 3288334335, speed 28811010 seeds per second seed = 3283082581 Found 3, trying 4261412864 - 4294967295, speed 28677071 seeds per second Found 3

爆破出了3個可能的種子,數量很少 手動一個一個測試:

<?phpmt_srand(735487048);//手工播種for($i=0;$i<21;$i++){ echo mt_rand()." ";}

輸出:

前20位跟上面腳本獲取的一模一樣,確認種子就是 1513334371 。有了種子我們就能計算出任意次數調用mt_rand()生成的隨機數了。比如這個腳本我生成了21位,最后一位是 1515656265 如果跑完剛才的腳本之后沒訪問過站點,那么打開 http://localhost/pid2.php 就能看到相同的 1515656265 。

所以我們得到結論:

php的自動播種發生在php cgi進程中第一次調用mt_rand()的時候。跟訪問的頁面無關,只要是同一個進程處理的請求,都會共享同一個最初自動播種的種子。

php_mt_seed

我們已經知道隨機數的生成是依賴特定的函數,上面曾經假設為 rand = seed+(i*10)  。對于這樣一個簡單的函數,我們當然可以直接計算(口算)出一個(組)解來,但 mt_rand() 實際使用的函數可是相當復雜且無法逆運算的。有效的破解方法其實是窮舉所有的種子并根據種子生成隨機數序列再跟已知的隨機數序列做比對來驗證種子是否正確。php_mt_seed^phpmtseed就是這么一個工具,它的速度非??欤芡?^32位seed也就幾分鐘。它可以根據單次mt_rand()的輸出結果直接爆破出可能的種子(上面有示例),當然也可以爆破類似mt_rand(1,100)這樣限定了MIN MAX輸出的種子(下面實例中有用到)。

安全問題

說了這么多,那到底隨機數怎么不安全了呢?其實函數本身沒有問題,官方也明確提示了生成的隨機數不應用于安全加密用途(雖然中文版本manual沒寫)。問題在于開發者并沒有意識到這并不是一個 真·隨機數 。我們已經知道,通過已知的隨機數序列可以爆破出種子。也就是說,只要任意頁面中存在輸出隨機數或者其衍生值(可逆推隨機值),那么其他任意頁面的隨機數將不再是“隨機數”。常見的輸出隨機數的例子比如驗證碼,隨機文件名等等。常見的隨機數用于安全驗證的比如找回密碼校驗值,比如加密key等等。一個理想中的攻擊場景:

夜深人靜,等待apache(nginx)收回所有php進程(確保下次訪問會重新播種),訪問一次驗證碼頁面,根據驗證碼字符逆推出隨機數,再根據隨機數爆破出隨機數種子。接著訪問找回密碼頁面,生成的找回密碼鏈接是基于隨機數的。我們就可以輕松計算出這個鏈接,找回管理員的密碼…………XXOO

實例

PHPCMS MT_RAND SEED CRACK致authkey泄露 雨牛寫的比我好,看他的就夠了

Discuz x3.2 authkey泄露 這個其實也差不多。官方已出補丁,有興趣的可以自己去分析一下。

總結

以上就是這篇文章的全部內容了,希望本文的內容對大家的學習或者工作具有一定的參考學習價值,如果有疑問大家可以留言交流,謝謝大家對VeVb武林網的支持。


注:相關教程知識閱讀請移步到PHP教程頻道。
發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表

圖片精選

亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
亚洲综合小说区| 久久久国产91| 精品久久久一区| 亚洲片av在线| 欧洲美女免费图片一区| 亚洲精品福利免费在线观看| 国产一区二区丝袜| 成人国产精品一区二区| 91综合免费在线| 欧美激情在线狂野欧美精品| 亚洲r级在线观看| 亚洲成色999久久网站| 国产亚洲精品高潮| 成人免费淫片视频软件| 韩国精品久久久999| 欧美精品免费在线观看| 国产精品麻豆va在线播放| 国产精品国产自产拍高清av水多| 国产成人a亚洲精品| 亚洲黄色在线看| 中文字幕亚洲欧美日韩2019| 亚洲a在线观看| 人人爽久久涩噜噜噜网站| 深夜成人在线观看| 一区二区三区在线播放欧美| 91av在线不卡| www.久久久久久.com| 国产精品久久久久久久电影| 日本精品久久电影| 欧美精品18videos性欧美| 国产成人a亚洲精品| 精品露脸国产偷人在视频| 精品一区电影国产| 日韩小视频在线| 欧洲日韩成人av| 丝袜亚洲欧美日韩综合| 成人午夜高潮视频| 成人乱人伦精品视频在线观看| 日韩av在线播放资源| 欧美亚洲视频在线看网址| 久久综合伊人77777蜜臀| 亚洲国产日韩欧美在线99| 亚洲欧美激情视频| 国模私拍视频一区| 亚洲欧美制服中文字幕| 久久久久久69| 一个人www欧美| 国产精品h片在线播放| 超薄丝袜一区二区| 97人洗澡人人免费公开视频碰碰碰| 久久综合伊人77777尤物| 日韩小视频在线观看| 最近更新的2019中文字幕| 久久香蕉国产线看观看av| 成人久久久久久久| 影音先锋欧美在线资源| 国产色婷婷国产综合在线理论片a| 91精品视频观看| 国产精品福利网站| 色吧影院999| 热久久免费视频精品| 国产精品永久免费视频| 亚洲人高潮女人毛茸茸| 亚洲美女精品久久| 日本精品视频在线观看| 91黑丝高跟在线| 亚洲黄色www网站| 欧美一级bbbbb性bbbb喷潮片| 色综合天天综合网国产成人网| 日韩免费av一区二区| 一本色道久久综合狠狠躁篇的优点| 成人免费xxxxx在线观看| 欧美成人免费va影院高清| 国产精品久久久久久久一区探花| 精品亚洲一区二区| 自拍视频国产精品| 在线亚洲男人天堂| 国产精品视频导航| 欧美激情久久久久| 欧美野外猛男的大粗鳮| 日韩欧美高清在线视频| 亚洲影视中文字幕| 色综合天天狠天天透天天伊人| 色哟哟亚洲精品一区二区| 成人综合国产精品| 亚洲国产精品久久久久秋霞蜜臀| 亚洲无限乱码一二三四麻| 久久国产精品免费视频| 日韩中文字幕网| 日韩久久免费电影| 亚洲欧美中文字幕在线一区| 神马国产精品影院av| 最近2019年手机中文字幕| 久久久免费观看| 日韩av影片在线观看| 亚洲国产精品系列| 亚洲一区二区三区777| 精品国产一区二区三区四区在线观看| 欧美日韩综合视频网址| 日韩色av导航| 视频直播国产精品| 久久乐国产精品| 日韩精品一区二区视频| 日韩电影中文字幕一区| 欧美猛少妇色xxxxx| 日韩在线视频网站| 日韩欧美中文免费| 亚洲第一级黄色片| 亚洲有声小说3d| 韩国v欧美v日本v亚洲| 亚洲天堂av在线播放| 国产成人高潮免费观看精品| 亚洲久久久久久久久久久| 91亚洲人电影| 日韩久久免费电影| 国产偷亚洲偷欧美偷精品| 黑人与娇小精品av专区| 久久精品国产精品亚洲| 欧美夫妻性生活视频| 欧美日韩一区二区三区在线免费观看| 亚洲一区二区自拍| 正在播放欧美一区| 26uuu另类亚洲欧美日本一| 欧美在线视频a| 亚洲精品国产精品国自产在线| 亚洲一区第一页| 成人深夜直播免费观看| 日韩视频一区在线| 亚洲的天堂在线中文字幕| 欧美性猛交xxxx富婆弯腰| 欧美国产日韩一区| 欧美激情视频免费观看| 国产福利视频一区| 日韩成人av在线| 97欧美精品一区二区三区| 精品高清一区二区三区| 久久精品国亚洲| 欧美精品成人在线| 精品高清一区二区三区| 国产精品中文字幕久久久| 欧美中文字幕精品| 久久伊人91精品综合网站| 国产精品视频xxx| 欧美日韩高清区| 国产主播喷水一区二区| 中文字幕欧美日韩va免费视频| 亚洲最新av在线| 欧美黄色性视频| 在线视频免费一区二区| 久久精品美女视频网站| 欧美在线视频免费播放| 奇米四色中文综合久久| 国产999精品久久久| 庆余年2免费日韩剧观看大牛| 久久久av电影| 欧美日韩精品在线视频| 国产精品福利在线观看网址| 精品丝袜一区二区三区| 日韩欧美综合在线视频| 日韩视频一区在线| 国产91色在线播放| 国产日韩中文在线| 九色精品免费永久在线| 欧美国产一区二区三区|