基礎:全面保護你的Java程式安全(中)(轉)

BSDLite發表於2007-08-15
基礎:全面保護你的Java程式安全(中)(轉)[@more@]第二部分:不要讓漏洞危及應用程式安全
概論:在這個部分的安全討論中,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);
}
你看出問題了嗎?
這個錯誤位於最後三行中(註釋和空格除外)。首先,安全管理器檢查可執行名,看其是否在配置檔案中有執行的授權。接下來,程式碼執行命令。哎喲!在一個多執行緒環境中,引數陣列內容在這兩步之間就可以改變。由於這兩個輸入引數陣列被直接使用,呼叫者仍然掌握著它們的引用,並且可以修改其內容。
更正:立即複製輸入陣列並在複製中進行操作。

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

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/10617542/viewspace-959833/,如需轉載,請註明出處,否則將追究法律責任。

相關文章