有 a - b < c 引發的安全性思考
軟件工程中,不論使用哪種開發語言,安全性一直是一個非常棘手卻又重要的問題。安全性是軟件開發領域永遠的主題之一,而且隨著互聯網的蜂擁發展而帶動的新技術的興起與革命(比如近幾年火起來的node.js,python,go等,甚至微軟也開源後的.net Core),軟件工程中的安全性更加的凸顯與重要了。
那麽,什麽才是危險的呢?我的第一反應是註入攻擊,比如SQL註入攻擊。一個典型的場景是WEB應用中,用戶登陸功能,根據用戶輸入的用戶名密碼獲取相應的數據,那麽SQL註入就應運而生,模擬用戶名,密碼加入特殊字符,加入惡意腳本等等手段,進而造成不了可挽回的後果。比如,正常腳本當如:
select* from userInfo where username=‘input_Name‘ and password=‘input_Pwd or‘
那麽,如果是這樣的呢?
select * from userInfo where username=‘input_Name‘ and password=‘input_Pwdte‘ or 1=1 or ‘‘
關於如何編寫安全的Java代碼,Sun官方給了一份指南,有興趣的同學可以參考這篇文章,大致為:
• 靜態字段
• 縮小作用域
• 公共方法和字段
• 保護包
• 如果可能使對象不可改變
• 不要返回指向包含敏感數據的內部數組的引用
• 不要直接存儲用戶提供的數組
• 序列化
• 原生函數
• 清除敏感信息
比如,DoS是一種常見的網絡攻擊,有人戲稱為“洪水攻擊”。其慣用手法是通過某種手段,比如大量的機器發送請求,將目標網站寬帶和其資源耗盡,導致用戶無法正常訪問,甚至服務器的宕機。
而對於此類問題,如果單從服務器級別考慮,多少欠缺,我們或許需要考慮程序級別的攻擊,比如Java,JVM,以及涉及到的線程方面的安全,應用程序的瑕疵等進行低成本的DoS攻擊。
而在面試中,我們都會被問到安全性的問題,卻大多比較多泛泛,大而廣,而大多數的安全性問題都與代碼安全性有關。我們回顧下Java代碼的運行過程:
首先編譯器把.java文件編程成.class字節碼文件,然後由類加載器負責把.class文件加載到JVM,再由字節碼校驗進行校驗,然後由Java解釋器負責把該類文件解釋為機器碼執行。
在類加載器加載.class文件到java虛擬機的過程中,類加載器通過區分本機文件系統的類和網絡系統導入的類增加安全性(不允許網絡上的應用程序修改本地的數據),本機的類先被加載,一旦所有的類加載完,執行文件的內存劃分就固定了,然後字節碼校驗器開始校驗.class字節碼文件,字節碼校驗器不檢查那些可信任的編譯器所產生的類文件。通過之後,java解釋器材負責把類文件解釋成為機器碼進行執行。
// a b c 都是int類型的數值 if (a - b < c) { // … }
這段看似簡單,沒毛病的代碼會引發下列問題:
如果b<0,而造成的數據溢出,你能想象出多少問題?!而對於越界的處理雖然Java底層給出了很好的解決,但是數值而造成內存問題不容小覷。
當然,過多的考慮安全性問題,勢必會造成應用程序的冗余甚至疲軟,這些需要視情況而定,而不可蓋棺而論。
再比如,對於一段可能出現問題的代碼,常用手段 try … catch(){… },那麽問題來了,catch的是什麽?而一般情況下,我們程序需要抓取到catch,因為要做日誌處理,那麽日誌中不可或缺的有類似代碼位置,方法名,以及錯誤原因等,甚至包含了敏感信息。當然,不可避免,我的建議是,盡量使用內部標識的異常信息,而返回給客戶端的類似異常消息盡量少的自動返回的異常消息。
對於安全標準特別高的系統,甚至可能要求敏感信息被使用後,要立即明確再內存中銷毀,以免被探測到;或者避免在發生core dump時,意外暴露。
開發和測試階段
1. 盡量的規範化代碼,可參考《阿裏巴巴開發手冊》
2. 盡量多的code review,避免不必要尷尬代碼出現
3. 在代碼check-in等環節,利用hook機制去調用規則檢查工具,保證不合規範代碼進入OpenJDK代碼庫
部署階段
可參考JDK在加密方法的路線圖
以上皆為日常開發總結,也借鑒網上大神的文章,略略整理一二,權作學習使用,當然面試能幫到不慎感動了,以後有機會再做梳理。
歡迎指點。
有 a - b < c 引發的安全性思考