隨機數安全的事

概述

隨機數在計算機應用中使用的比較普遍,最爲熟知的即是在密碼學中的應用。本文主要是講解隨機數使用致使的一些Web安全風。php

咱們先簡單瞭解一下隨機數java

分類

隨機數分爲真隨機數和僞隨機數,咱們程序使用的基本都是僞隨機數,其中僞隨機又分爲強僞隨機數和弱僞隨機數。程序員

真隨機數,經過物理實驗得出,好比擲錢幣、骰子、轉輪、使用電子元件的噪音、核裂變等算法

僞隨機數,經過必定算法和種子得出。軟件實現的是僞隨機數apache

強僞隨機數,難以預測的隨機數安全

弱僞隨機數,易於預測的隨機數服務器

特性

隨機數有3個特性,具體以下:網絡

隨機性:不存在統計學誤差,是徹底雜亂的數列架構

不可預測性:不能從過去的數列推測出下一個出現的數框架

不可重現性:除非將數列自己保存下來,不然不能重現相同的數列

隨機數的特性和隨機數的分類有必定的關係,好比,弱僞隨機數只須要知足隨機性便可,而強位隨機數須要知足隨機性和不可預測性,真隨機數則須要同時知足3個特性。

引起安全問題的關鍵點在於不可預測性。

僞隨機數的生成

咱們日常軟件和應用實現的都是僞隨機數,因此本文的重點也就是僞隨機數。

僞隨機數的生成實現通常是算法+種子。

具體的僞隨機數生成器PRNG通常有:

線性同餘法

單向散列函數法

密碼法

ANSI X9.17

比較經常使用的通常是線性同餘法,好比咱們熟知的C語言的rand庫和Java的java.util.Random類,都採用了線性同餘法生成隨機數。

應用場景

隨機數的應用場景比較普遍,如下是隨機數常見的應用場景:

驗證碼生成

抽獎活動

UUID生成

SessionID生成

Token生成

CSRF Token

找回密碼Token

遊戲(隨機元素的生成)

洗牌

俄羅斯方塊出現特定形狀的序列

遊戲爆裝備

密碼應用場景

生成密鑰:對稱密碼,消息認證

生成密鑰對:公鑰密碼,數字簽名

生成IV: 用於分組密碼的CBC,CFB和OFB模式

生成nonce: 用於防護重放攻擊; 分組密碼的CTR模式

生成鹽:用於基於口令的密碼PBE等

0x02 隨機數的安全性

相比其餘密碼技術,隨機數不多受到關注,但隨機數在密碼技術和計算機應用中是很是重要的,不正確的使用隨機數會致使一系列的安全問題。

隨機數的安全風險

隨機數致使的安全問題通常有兩種

應該使用隨機數,開發者並無使用隨機數;

應該使用強僞隨機數,開發者使用了弱僞隨機數。

第一種狀況,簡單來說,就是咱們須要一個隨機數,可是開發者沒有使用隨機數,而是指定了一個常量。固然,不少人會義憤填膺的說,sb纔會不用隨機數。可是,請不要忽略我朝仍是有不少的。主要有兩個場景:

開發者缺少基礎常識不知道要用隨機數;

一些應用場景和框架,接口文檔不完善或者開發者沒有仔細閱讀等緣由。

好比找回密碼的token,須要一個僞隨機數,不少業務直接根據用戶名生成token;

好比OAuth2.0中須要第三方傳遞一個state參數做爲CSRF Token防止CSRF攻擊,不少開發者根本不使用這個參數,或者是傳入一個固定的值。因爲認證方沒法對這個值進行業務層面有效性的校驗,致使了OAuth的CSRF攻擊。

第二種狀況,主要區別就在於僞隨機數的強弱了,大部分(全部?)語言的API文檔中的基礎庫(經常使用庫)中的random庫都是弱僞隨機,不少開發天然就直接使用。可是,最重要也最致命的是,弱僞隨機數是不能用於密碼技術的。

仍是第一種狀況中的找回密碼場景,關於token的生成, 不少開發使用了時間戳做爲隨機數(md5(時間戳),md5(時間戳+用戶名)),可是因爲時間戳是能夠預測的,很容易就被猜解。不可預測性是區分弱僞隨機數和強僞隨機數的關鍵指標。

固然,除了以上兩種狀況,還有一些比較特別的狀況,一般狀況下比較少見,可是也不排除:

種子的泄露,算法不少時候是公開的,若是種子泄露了,至關於隨機數已經泄露了;

隨機數池不足。這個嚴格來講也屬於弱僞隨機數,由於隨機數池不足其實也致使了隨機數是可預測的,攻擊者能夠直接暴力破解。

漏洞實例

wooyun上有不少漏洞,還蠻有意思的,都是和隨機數有關的。

PS:我的實力有限,如下實例基本都來自wooyun漏洞實例,在這裏謝謝各位大牛,若有侵權,請聯繫刪除。

1.應該使用隨機數而未使用隨機數

Oauth2.0的這個問題特別經典,除了wooyun實例列出來的,其實不少廠商都有這個問題。

Oauth2.0中state參數要求第三方應用的開發者傳入一個CSRF Token(隨機數),若是沒有傳入或者傳入的不是隨機數,會致使CSRF登錄任意賬號:

惟品會帳號相關漏洞可經過csrf登陸任意帳號

人人網-百度OAuth 2.0 redirect_uir CSRF 漏洞

2.使用弱僞隨機數

1) 密碼取回

不少密碼找回的場景,會發送給用戶郵件一個url,中間包含一個token,這個token若是猜想,那麼就能夠找回其餘用戶的密碼。

1.Shopex 4.8.5密碼取回處新生成密碼可預測漏洞

直接使用了時間函數microtime()做爲隨機數,而後獲取MD5的前6位。

substr(md5(print_r(microtime(),true)),0,6); 

PHP 中microtime()的值除了當前服務器的秒數外,還有微秒數,微妙數的變化範圍在0.000000 -- 0.999999 之間,通常來講,服務器的時間能夠經過HTTP返回頭的DATE字段來獲取,所以咱們只須要遍歷這1000000可能值便可。但咱們要使用暴力破解的方式 發起1000000次網絡請求的話,網絡請求數也會很是之大。但是shopex很是貼心的在生成密碼前再次將microtime() 輸出了一次:

$messenger = &$this->system->loadModel('system/messenger');echo microtime()."
"

2.奇虎360任意用戶密碼修改

直接是MD5(unix時間戳)

3.塗鴉王國弱隨機數致使任意用戶劫持漏洞,附測試POC

關於找回密碼隨機數的問題強烈建議你們參考拓哥的11年的文章《利用系統時間可預測破解java隨機數| 空虛浪子心的靈魂》

2) 其餘隨機數驗證場景

CmsEasy最新版暴力注入(加解密缺陷/繞過防注入)

弱僞隨機數被繞過

Espcms v5.6 暴力注入

Espcms中一處SQL注入漏洞的利用,利用時發現espcms對傳值有加密而且隨機key,可是這是一個隨機數池固定的弱僞隨機數,能夠被攻擊者遍歷繞過

Destoon B2B 2014-05-21最新版繞過全局防護暴力注入(官方Demo可重現)

使用了microtime()做爲隨機數,能夠被預測暴力破解

Android 4.4以前版本的Java加密架構(JCA)中使用的Apache Harmony 6.0M3及其以前版本的SecureRandom實現存在安全漏洞,具體位於classlib/modules/security/src/main /java/common/org/apache/harmony/security/provider/crypto/SHA1PRNG_SecureRandomImpl.java

類的engineNextBytes函數裏,當用戶沒有提供用於產生隨機數的種子時,程序不能正確調整偏移量,致使PRNG生成隨機序列的過程可被預測。

Android SecureRandom漏洞詳解

安全建議

上面講的隨機數基礎和漏洞實例更偏重是給攻擊者一些思路,這裏更多的是一些防護和預防的建議。

業務場景須要使用隨機數,必定要使用隨機數,好比Token的生成;

隨機數要足夠長,避免暴力破解;

保證不一樣用處的隨機數使用不一樣的種子

對安全性要求高的隨機數(如密碼技術相關)禁止使用的弱僞隨機數:

不要使用時間函數做爲隨機數(不少程序員喜歡用時間戳) Java:system.currenttimemillis() php:microtime()

不要使用弱僞隨機數生成器 Java: java.util.Random PHP: rand() 範圍很小,32767 PHP: mt_rand() 存在缺陷

強僞隨機數CSPRNG(安全可靠的僞隨機數生成器(Cryptographically Secure Pseudo-Random Number Generator)的各類參考

6.強僞隨機數生成(不建議開發本身實現)

產生高強度的隨機數,有兩個重要的因素:種子和算法。算法是能夠有不少的,一般如何選擇種子是很是關鍵的因素。 如Random,它的種子是System.currentTimeMillis(),因此它的隨機數都是可預測的, 是弱僞隨機數。

強僞隨機數的生成思路:收集計算機的各類信息,鍵盤輸入時間,內存使用狀態,硬盤空閒空間,IO延時,進程數量,線程數量等信息,CPU時鐘,來獲得一個近似隨機的種子,主要是達到不可預測性

相關文章
相關標籤/搜索