源碼掃描 – Insecure Randomness 不安全的隨機數

發生了什麼事

這幾天被丟到廠商那邊去修源碼掃描了( ´•̥̥̥ω•̥̥̥` ) ,雖然剛好拯救了最近在思考要寫些什麼的我

另外,其實寫程式多年,修過的源碼掃描也是屈指可數哈哈

所以整理下來供未來的大家參考參考也不錯

(另外本篇文章會以Java的角度去說明如何修正,其他語言的範例可能有機會再補充)

Insecure Randomness 不安全的隨機數

根據 OWASP(*註1) 的說明,其實核心意思就是 「使用不安全的隨機數生成器,例如偽隨機數生成器(PRNG),而非真隨機數生成器(TRNG),而導致的安全漏洞。」

PRNG (Pseudo Random Number Generator) 偽隨機數生成器

是一個生成數字序列的算法,其產生之序列並不是真的完全隨機,而是受到一個初始值,又被稱為seed來決定。

通常拿來做兩種用途,統計用以及

  • 速度優勢 – 因使用電腦程式來計算,故速度極快
  • 安全性 – 因要是攻擊者得知seed,相當於攻擊者知道了整個序列

TRNG (True Random Number Generator) 真隨機數生成器

是一個透過物理而不是電腦來產生隨機數的方式,如光電、熱力、噪音…等現象,透過轉換以及重複採樣來得到序列。

  • 速度較慢 – 因需收集物理現象,故採集以及生成都需時間
  • 安全性 – 相當高,理論上是無法預測的

➡跨界合作 : 其實現在有一些的解決方法就是讓 TRNG 去產生一個隨機的seed供 PRNG 使用

這樣子可以在兼顧效率的同時也兼顧了一定的安全性

該怎麼修正 – Java篇

(雖然是以Java作為範例,但各語言應該都是類似的)

Random random = new Random();
int test = random.nextInt();

⬆️為什麼沒有設定seed呢,是因為預設會以系統時間(到毫秒)來作為seed並帶入

而這時候,random 就會因為它的安全性被掃出來

故可以改成如下,避免安全性過低的問題

import java.security.SecureRandom
.
.
SecureRandom random = new SecureRandom();
int test = random.nextInt();

引用了另一類的SecureRandom方式 – 不過其實它不是 TRNG ,而是另一種加密型的 PRNG

具體上來說,比起Random不一樣的是

使用了各種來源的熵來生成隨機數,例如 : 系統時鐘、系統事件和來自周圍環境的噪音

這邊來做個簡單的比較

特性 TRNGSecureRandomRandom
使用物理過程
是否完全隨機
安全性最高適中最低
成本最高最低

其中new SecureRandom() 就會使用可用的任何隨機數生成算法去產生序列。

另外,其實也可以改成 SecureRandom random = SecureRandom.getInstanceStrong();

根據各式文件及說明看到的是,比起本來的隨機演算法,這個寫法會特別優先使用高級別強度的演算法。


結論

那究竟隨機數能不能使用 PRNG 呢?

答案其實還是可以

但可能要注意以下幾點,可以有效的降低風險

  • 第一點就是該系統的安全性需求,若是真的國家等級的機密,那拜託你還是使用 TRNG 或是更高層級的方式進行保護
  • 定期更換種子值
  • 使用加密安全的 PRNG – 例如這次使用的 SecureRandom

這次源碼掃描用的軟體是 Fortify,報告出來超厲害的ㄟ!!

不僅提供了問題的詳細描述,連範例跟該範例如何修正都有提供,為修正提供了一個方向

這個系列希望能多寫幾篇,畢竟大家在程式上線前一定會進行安全性掃描的

希望能幫到大家一點修正的方向

參考文章 :

註1 : OWASP 是一個非營利的國際組織,致力於提高Web 應用程序的安全性,提供了各式教學以及工具,其中的成員遍佈世界各地(包含資訊安全專家、開發人員…等)

🧡文章如果有幫上忙,那就太棒了 !

🧡幫我分享給朋友或是留下您寶貴的意見,都是對我的支持

✅如有任何疑問,歡迎透過留言或messenger讓我知道 ! (都沒人找我聊天QQ)

走過的路程。都寫成了筆記 (源碼掃描多寫幾篇,可能會改成相關的文章)

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *