歡迎您光臨本站 註冊首頁

全面保護你的Java程序安全(中)

←手機掃碼閱讀     火星人 @ 2014-03-12 , reply:0
  第二部分:不要讓漏洞危及應用程序安全

概論:在這個部分的安全討論中,Todd Sundsted和我們一起討論應用程序安全問題。在程序開發中的微小錯誤都可能給開發人員和用戶帶來很大的安全問題。Todd在這裡將展示如何設計及實現這種最普通的安全漏洞類型,並描述了如何避免這些問題。他還提供了一個來自Sun自己JDK中的一個漏洞示列。

大多數軟體開發人員都能意識到那些惡意或是僅僅是好奇的黑客所帶來的威脅,但很少開發者認識到他們無意中帶到程序中的漏洞造成的影響範圍有多大。這些帶到程序中的漏洞無疑縱容,幫助了所謂的黑客們。

在今年一月,一名德國的軟體開發人員證實在最近開發源代碼產品Borland的資料庫 InterBase中有個帶有嚴重安全隱患的設計上的漏洞。在這個InterBase版本中的漏洞甚至可以追溯回到1994年!

這個存在於登錄名和密碼驗證窗體上的後門並非有人故意為之。然而,正是InterBase開發人員不當的設計造成了這個問題。這個程序使用了命名和密碼驗證來控制InterBase接入資料庫。

儘管這個錯誤展現的是個極端的列子,但它所揭示的教訓是很重要的:作為開發者,對於我們應用程序整體安全,我們的設計以及代碼實現是非常關鍵的。並且,如上面的列子所示,由開發者帶入程序中的漏洞可能會影響用戶達數年時間。

·回顧

上次,我們討論了我們必須檢查三方面的安全問題。這些問題儘管互不相同,但經常要求跨越三方面進行全面的考慮。Java程序的開發者必須要明白從這三方面來考慮他們解決方案的安全性問題對其產品的重要意義。

Java和非Java的開發者對這樣一個最知名的安全問題都是熟悉的,那就是虛擬機安全。這源於對於JVM和運行時環境多年來大量的關注。虛擬機安全包含JVM和提供支持的運行時環境。在過去的幾年裡,虛擬機安全問題得到了加強,並得到了很好的重視。

最近,由於在JVM領域明顯的漏洞已少,多數編程者的注意力已經從Java虛擬機安全轉向到運行於其上的應用程序安全。而這些多數Java程序員在這層面將明顯的影響到Java安全。在這方面,需要處理的是設計決定以及在開發中可能出現的意外問題。當然,不是所有這樣的漏洞都會危及應用程序安全。我們將集中精力於那些能夠危害程序的漏洞。

最後一方面的問題,網路安全問題,其基於網路的程序和程序組件之間的通信問題是安全問題方面的一個糧亮點。再次聲明,不是所有這裡介紹的漏洞都會危及安全,我們只注意那些能夠危及安全的方面。

上次我們討論了虛擬機安全問題並示範了VM安全方面的漏洞如何出現及進行破壞的。現在,我將討論應用程序安全。這裡,我舉出一個最普通的有漏洞的類,以助你避免這樣的問題。我會包含最近在Sun自己的代碼中發現的列子。

很容易列出一個各種錯誤設計以及實現的列表清單,這裡要說的列子只是其中的一個。但我將定義和描述出大多數Java程序安全弱點的一個分類目錄。這個目錄主要分為兩大塊:「實現相關」和「設計相關」的漏洞。

·實現相關的漏洞:

實現相關的漏洞通常是在實現代碼時帶入到程序中的。這通常是由於粗枝大葉的代碼編寫,對需求理解不夠充分,以及不熟練的編程技能等造成。實現相關的漏洞由於不充足的測試以及複核而常常隱藏的比較深。然而,如果系統設計良好,你就可以不改變設計而更正這些漏洞:

·定時問題:

最有害的定時問題是資源競爭問題。這樣的問題在當兩個沒有經過適當同步的線程同時爭奪同一個資源時發生。在這兩個互相影響的線程或者是在不懈調,無效的狀態下放棄對象,或者是當惡意代碼利用了正被另一個線程使用又沒有被很好的保護的資源時,安全漏洞就會出現。通常的解決辦法是簡單的加上同步措施。

·不充分的輸入校驗:

系統的輸入在使用前一定要經過檢驗。儘管某些輸入是來自信任源,但出於安全考慮,所有這些輸入都應該看作不被信任的,危險源。未經完全檢查的輸入可能帶來大量嚴重的安全弱點。

·不當的隨機數:

好的加密系統需要高質量的隨機數發生器。早前Netscape Navigator的大量安全漏洞直接就是來自於不適當的隨機數發生器。隨機數發生器產生的有效密匙達不到建議的長度,結果很容易遭到破解。

·設計缺陷:

源自於實現部分的安全問題已經很糟糕,但最壞的情況是由於設計上的缺乏長遠考慮,對語言及函數庫的理解不夠充分而引起的。這種漏洞通常使程序邏輯糾纏不清,必須花掉大量時間和耐心去處它,即便這樣也會是很困難的事。上面提到的InterBase漏洞就是極好的這樣的列子。

·初始化問題:

大家都知道「new」操作並不是創建新實列的唯一方法。像克隆這樣的方法也可以創建新的實列。你可以通過非常規的方法創建實列,以搞亂類的安全系統。

·可見性和擴展性問題:

可見性(類或是其成員是否是公共的或是私有的),擴展性(子類是否能繼承一個類或是方法)為軟體開發人員提供了非常重要的工具。然而,如果使用不當,這也會造成一些微妙的漏洞。

在子類化的列子中,一個子類可以改變繼承自超類的約定,定義。擴展后的代碼使用一些自己的約定可以破壞程序安全。解決辦法就是:合理使用「final」關鍵字,防止子類進行重定義。

同樣,你可以通過使用關鍵字「private」防止類內部流程和狀態被修改,反之,則可能將類內部細節暴露在隨後添加到包中的類下。

·絕不要放置「後門」:

InterBase的設計就給我們提供了這樣一個列子。你不能私自在程序裡面建立什麼後門代碼。這些代碼通常是位於密碼校驗和加密數據的窗體。這對於一個固執的黑客來說根本夠不成障礙。一旦後門被破解,「潘多拉的魔盒」就打開了。

·Sun自己也會犯錯:

我非常尊敬Sun的工程師。然而,儘管他們都是很有天賦的人,但還是如你我一樣會犯錯誤。
在2月23號,Sun宣布它發現了JDK中的一處漏洞。下面是他們的聲明:

「在某些Java運行時版本中的漏洞可能會允許惡意Java代碼執行未經授權的命令。然而,惡意命令代碼一定已經取得了代碼執行的授權。」

如果這種代碼在某種環境下被給予執行至少一條可執行命令(如echo),這個漏洞會允許不被信任的Java代碼激活任何可執行命令(如格式化FORMAT)。這樣的錯誤很可能隱藏很久而不被發現。

下面就讓我們來看看具體的代碼:這個漏洞是位於java.lang.Runtime類里的exec()方法中:
public Process exec(String [] arstringCommand, String [] arstringEnvironment)
throws IOException
{
// Ensure that the array parameters aren't null, their elements
// aren't null, etc.
  .
.
.
// Do some stuff.
.
.
.
// Get the security manager.
SecurityManager securitymanager = System.getSecurityManager();
// Check the first element of the command array -- which should
// be the name of the executable to invoke. Ensure that it has
// executable privilege.
if (securitymanager != null)
securitymanager.checkExec(arstringCommand[0]);
// Now, invoke the executable.
return execInternal(arstringCommand, arstringEnvironment);
}

你看出問題了嗎?

這個錯誤位於最後三行中(註釋和空格除外)。首先,安全管理器檢查可執行名,看其是否在配置文件中有執行的授權。接下來,代碼執行命令。哎喲!在一個多線程環境中,參數數組內容在這兩步之間就可以改變。由於這兩個輸入參數數組被直接使用,調用者仍然掌握著它們的引用,並且可以修改其內容。

更正:立即複製輸入數組並在拷貝中進行操作。

·回到最好的練習:

經由老式的軟體開發練習,你可以發現很多導致安全問題的漏洞。清楚的需求,嚴格的設計核查,完整的代碼核查,並通過詳盡的測試可以挖出很多漏洞並進一步提高軟體整體質量。


[火星人 ] 全面保護你的Java程序安全(中)已經有317次圍觀

http://coctec.com/docs/program/show-post-72196.html