在我從業(yè)的這么多年時間里,我為各種小型初創(chuàng)企業(yè)、大型銀行以及電信運營商進行過無數(shù)次的代碼安全審計,而且在閑暇時間我也閱讀過stackoverflow.com上數(shù)百篇的安全文章。至此,我總結(jié)出了目前開發(fā)人員最容易犯的十大加密錯誤。本系列分上下集,希望大家能夠從中得到一些加密方面的啟示。
不幸的是,錯誤使用加密方法的情況比比皆是,而且錯誤使用的情況遠遠要比正確使用的情況出現(xiàn)得更加頻繁。不過,很多問題是由于加密API本身的復(fù)雜性(開發(fā)文檔描述不清)和不安全性(默認配置不安全)所導(dǎo)致的,也并非錯誤都處在開發(fā)人員的身上。Java可以算得上是目前存在問題最為嚴重的開發(fā)語言之一,而也許Java應(yīng)該從它的“敵人” .Net身上學(xué)到一些東西,例如如何開發(fā)出更加方便使用的加密API,或者降低安全問題出現(xiàn)的可能性等等。
導(dǎo)致目前情況不容樂觀的另外一個原因也許是很多安全問題往往需要我們對代碼進行人工分析才可以發(fā)現(xiàn),而只有經(jīng)過專業(yè)培訓(xùn)的安全專家才能夠完成這項任務(wù)。根據(jù)我的從業(yè)經(jīng)驗來看,很多熱門的靜態(tài)分析工具在尋找加密方面的問題時效率和成功率都不高,而且黑盒滲透測試幾乎無法發(fā)現(xiàn)這種問題。
因此,我希望這篇文章中的內(nèi)容可以幫助那些代碼審計人員以及開發(fā)者們提高對軟件加密方面的認知。
文章結(jié)構(gòu)如下:
1. 硬編碼密鑰
2. 初始化向量選擇不當(dāng)
3. ECB操作模式
4. MD5死而不僵,SHA1仍茍存于世
5. 誤用加密原語(用于密碼存儲)
6. 密碼未加密
7. 通過加密保證信息完整性
8. 非對稱密鑰長度不足
9. 不安全的隨機性
10. 加密雞湯
接下來,讓我給大家細細道來。
一、 硬編碼密鑰
這種情況非常的常見,硬編碼密鑰往往意味著能夠訪問軟件的人手中都有可以解密數(shù)據(jù)的密鑰(對于那些想說“代碼混淆”的開發(fā)人員,我已經(jīng)為你準(zhǔn)備好了第十條)。理想情況下,我們并不希望加密密鑰能夠?qū)θ祟惪梢姡@畢竟是理想狀態(tài)。因此,我們只能退而求其次地去限制密鑰的訪問,并且只允許安全團隊訪問這個密鑰,而開發(fā)人員不允許訪問產(chǎn)品密鑰,尤其是那些本不應(yīng)該出現(xiàn)在源代碼庫中的密鑰。

硬編碼密鑰也表現(xiàn)出了開發(fā)人員對密鑰管理方面的問題思考不足。密鑰管理是一個非常復(fù)雜的話題,并且超出了本文所要討論的范圍。但我想表達的是,如果密鑰被攻擊了,那么我們只有發(fā)布新版本的軟件才能替換掉原先已被攻擊的硬編碼密鑰,而在發(fā)布新版本之前往往需要大量的時間和成本來進行測試,但是在密鑰已被破解的情況下這種成本是必須要承擔(dān)的。
安全專家可以輕松地告訴開發(fā)人員那些是不應(yīng)該做的,但事實卻總是不盡如人意,因為出于某種原因,我們想讓他們做到的往往在實踐過程中是不可行的。因此,開發(fā)人員通常需要采取一些折中措施。
因此我認為,使用一個配置文件可能會是更好的選擇,雖然這并不是完美的解決方案,但這至少要比使用硬編碼密鑰要好得多。雖然某些框架提供了加密配置選項,但開發(fā)人員真正需要的是一個用于測試環(huán)境和開發(fā)環(huán)境的測試密鑰,而安全技術(shù)團隊可以在真正將產(chǎn)品投放市場時用真正的密鑰來替換掉測試密鑰。
上面的這個建議是我在一個真實的案例中所總結(jié)出來的。當(dāng)時,有一個研發(fā)團隊在產(chǎn)品中錯誤地存放了一個RSA公鑰,而這個密鑰是無法進行解密的,因為他們手中并沒有并沒有相對應(yīng)的私鑰。而我認為,軟件需要一種測試方法來確保其中的密鑰可以正常加密/解密,或者至少開發(fā)過程中需要有一個環(huán)節(jié)來確保程序能夠按照預(yù)期運行。
二、 初始化向量(IV)選擇不當(dāng)
IV指的是初始化向量。這種情況往往出現(xiàn)在CBC加密模式的使用過程中,而且通常存在于硬編碼IV中。有時開發(fā)人員會使用密鑰或SALT值,但最終的結(jié)果仍是每一次使用的都是相同的IV。我所見過的最糟糕的情況,就是將密鑰當(dāng)作IV來使用。我在Crypto101的7.6章討論了這種行為的危險性,感興趣的同學(xué)可以自行點擊查閱。【傳送門】

當(dāng)你在使用CBC加密模式時,你需要使用隨機的或不可預(yù)測的IV。在Java中,使用SecureRandom;在.Net中,使用GenerateIV。而且你這一次選擇出的IV只能使用一次,你不可以在其他加密過程中再一次使用這個IV。對于每一次加密,你都要生成一個新的IV。如果你沒有選擇出何時的IV,那么加密的安全性就得不到保障了,一個最好的例子就是SSL/TLS的實現(xiàn),其中牽扯到大量選擇不當(dāng)?shù)腎V。
如果你想了解更多關(guān)于初始化向量(IV)和隨機數(shù)的操作模式,請參考這篇文章。【傳送門】
三、 ECB模式
當(dāng)你在使用AES這樣的分組密碼進行加密時,你應(yīng)該選擇一種滿足你需要的操作模式。而你最不應(yīng)該選擇的就是ECB(電碼本)模式。
無論你使用的是哪一種分組密碼,但如果你使用了ECB模式,那就是非常不安全的,因為它會泄漏明文信息,尤其是當(dāng)重復(fù)的明文變成重復(fù)的密文時。如果你認為這不重要,那么請你看一看下面這張圖片:

你可以看到,采用ECB模式加密后的結(jié)果保密性非常差,而采用類似CBC和CTR這樣的安全加密模式則安全性會有大幅提升。需要注意的是,像Java這樣的編程語言所提供的API默認使用的是ECB模式。
簡而言之,不要使用ECB模式。如果你想了解更多有關(guān)安全加密模式的內(nèi)容,請參考這篇文章。【傳送門】四、 MD5死而不僵,SHA1仍茍存于世
實際上,MD5早在10年前就已經(jīng)被破解了,而安全人員更加在20年前就已經(jīng)開始警告不要再去使用MD5了。但是我發(fā)現(xiàn),現(xiàn)在有很多人仍在使用它。
而理論上SHA1也早已被破解,但外界真正見到的首次攻擊是近期才被曝光的。這一點Google就做得非常好,他們在研究人員正式宣布SHA1被破解之前就已經(jīng)放棄在證書中使用SHA1了,但由于歷史遺留問題,很多開發(fā)源碼中仍然有SHA1的存在。

每當(dāng)我在開發(fā)者的代碼中看到加密哈希函數(shù)的身影時,我都會非常擔(dān)心,因為這些人通常都不知道自己將要面對的是什么。在密碼學(xué)領(lǐng)域中,消息認證代碼、數(shù)字簽名算法、以及各種偽隨機數(shù)生成器使用的通常都是哈希函數(shù),但如果讓開發(fā)人員直接使用哈希函數(shù)的話,就像是把一支機關(guān)槍交到了一名八歲小孩的手上一樣,鬼知道會發(fā)生什么。各位開發(fā)者們,你們確定這些函數(shù)真的是你需要的嗎?
總結(jié)
接下來,我們會在本系列文章的下集中跟大家詳細討論剩下的六大開發(fā)者可能會遇到的加密問題,感興趣的同學(xué)可以關(guān)注黑吧安全網(wǎng)的最新動態(tài)。
|