網絡技術是從1990年代中期發展起來的新技術,它把互聯網上分散的資源融為有機整體,實現資源的全面共享和有機協作,使人們能夠透明地使用資源的整體能力并按需獲取信息。資源包括高性能計算機、存儲資源、數據資源、信息資源、知識資源、專家資源、大型數據庫、網絡、傳感器等。 當前的互聯網只限于信息共享,網絡則被認為是互聯網發展的第三階段。 鎖文件 通常,類 Unix 系統是通過創建表示一個鎖的文件來實現不同進程間共享的鎖。使用單獨的文件來表示鎖,是“勸告式(advisory)”鎖而不是“強制(mandatory)”鎖的一個例子。換句話說,操作系統不會強制您通過鎖來共享資源,所以,所有需要該資源的進程都必須協同使用該鎖。這看起來好像很簡單,但并不是所有簡單的主意都不是好主意;創建單獨的文件,就可以方便地獲得系統的狀態,其中包括哪些資源被加鎖了。如果您使用這種方法,有一些標準的技巧可以簡化這些鎖的清除,具體地說,是刪除那些掛起的鎖。例如,一個父進程可以設置一個鎖,然后調用一個子進程來執行工作(確保父進程可以有效地調用子進程),當子進程返回時,父進程釋放該鎖。或者,可以使用 cron 作業來查看那些鎖(其中包括進程的 id);如果進程沒有處于活動狀態,那么該作業就會清除那些鎖,并重新啟動相應的進程。最后,鎖文件的清除可以作為系統啟動的一部分(從而使您的鎖在系統突然崩潰之后不再處于掛起狀態)。 如果您正在創建單獨的文件來表示鎖,那么要注意一個常見的錯誤:對 creat() 或者與之相當的 open() 的調用(模式為 O_WRONLY | O_CREAT | O_TRUNC)。問題是,root 總是 可以這樣創建文件,即便鎖文件已經存在,這意味著該鎖不能為 root 正常工作。簡單的解決方案是在使用 open() 時指定標記 O_WRONLY | O_CREAT | O_EXCL(將權限設置為 0,使同一用戶的其他進程無法獲得該鎖)。注意 O_EXCL 的使用,這是創建“專用”文件的正式途徑;甚至在本地文件系統上,root 也可以這樣做。這個簡單的方法對 NFS 版本 1 或者版本 2 不適用;如果必須在使用這些老的 NFS 版本連接的遠程系統上使用鎖文件,那么可以使用 Linux 文檔中給出的方案:“在相同的文件系統上創建一個惟一的文件(例如,結合主機名和 pid),使用 link(2) 來創建一個指向鎖文件的鏈接,使用 stat(2) 來檢查該惟一文件的鏈接計數器是否增加到了 2。不要使用 link(2) 調用的返回值。” 如果您使用文件來表示鎖,那么要確保這些鎖文件放置在攻擊者無法利用(例如,不能刪除它們或者添加干擾它們的文件)的位置。典型的解決方案是使用一個目錄,使該目錄的權限根本不允許未經授權的程序添加或者刪除文件。確保只有您可以信任的程序才能添加或者刪除鎖文件! 文件系統層次結構標準(Filesystem Hierarchy Standard,FHS)得到了 Linux 系統的廣泛使用,同時還引入了這類鎖文件的標準約定。如果您只是希望確保您的服務器在一臺給定的機器上運行不超過一次,那么您通常應該創建一個名為 /var/run/NAME.pid 的進程標識符,以進程 id 作為文件內容。根據同樣的思路,您應該將設備鎖文件之類的鎖文件放置在 /var/lock 中。 鎖文件的代替者 使用單獨的文件來表示鎖是一個非常古老的方法。另一個方法是使用 POSIX 記錄鎖(record locks),它通過 fcntl(2) 實現為一個任意的鎖。采用 POSIX 記錄鎖的理由有很多:POSIX 記錄鎖在幾乎所有的類 Unix 平臺上都獲得了支持(它得到了 POSIX.1 的授權),它可以鎖定文件的一部分(而不是只會鎖定整個文件),而且它可以區別處理讀鎖和寫鎖的不同之處。此外,如果一個進程死掉,那么它的 POSIX 記錄鎖就會自動被刪除。 只有所有程序都共同合作的時候,使用單獨的文件或者 fcntl(2) 任意鎖才能生效。如果您不喜歡該思想,那么可以轉而使用 System V 風格的強制鎖。強制鎖允許您鎖定一個文件(或者它的一部分),使每一次 read(2) 和 write(2) 都檢查鎖,任何沒有持有該鎖的操作都將被掛起,直到該鎖被釋放為止。這樣做可能稍微方便一些,但也有其缺點;擁有 root 特權的進程也可能被強制鎖掛起,這樣通常容易造成拒絕服務(denial-of-service)攻擊。實際上,拒絕服務問題是非常嚴重的,因此通常要避免使用強制鎖。強制鎖是可用范圍很廣,但它不是通用的;Linux 和基于 System V 的系統支持這種鎖,但其他的類 Unix 系統不支持它。在 Linux 上,為了啟用強制文件鎖,必須用特定的方式裝配文件系統,因此很多配置在默認情況下不支持強制文件鎖。 在一個進程內部,線程可能也同樣需要鎖;有很多書都非常詳細地討論了這些問題。在這里,我們要討論的主要問題是確保您小心地涵蓋了所有情況;很容易忘記某個特定情形,或者沒有正確處理。事實上,正確使用鎖是很難的,攻擊者可能利用這些鎖處理中的錯誤。如果您需要在一個進程內部對線程使用很多鎖,那么可以考慮使用自動完成鎖的維護的語言或者語言結構。有很多語言,比如 Java 和 Ada95,都有內置的可以自動處理鎖維護(并使結果有可能更正確)的語言結構。 只要有可能,在開發程序時最好根本不使用鎖。一個單獨的服務器進程每次只接受一個客戶機請求,然后處理該請求,直到完成該請求為止,而后再獲得下一個請求,從某種意義上講,進程內部的所有對象是被自動鎖定的;這種簡單的設計可以避免很多危險的加鎖問題。如果您需要一個鎖,那么保持其簡單性(比如為幾乎所有內容都使用惟一的鎖)是有好處的。這并不總是實用的,因為這樣設計有時會損害性能。具體地說,單服務器系統需要確保無論哪個操作都無法占用過長的時間。但是這個建議是值得考慮的;使用很多鎖的系統會更可能有缺陷,而且維護這些鎖也會影響性能。 處理文件系統 安全程序的編寫必須確保攻擊者無法以導致問題的方式利用共享的資源,有時這并不像看起來那樣容易辦到。文件系統是最常見的共享資源之一。所有的程序都可以共享文件系統,所以,有時需要額外的努力,以確保攻擊者不能以引發問題的方式利用文件系統。 有很多確定為安全的程序都存在稱為“time of check - time of use”(TOCTOU)的競爭條件缺陷。這只說明了程序檢查某種情形是否可行,然后稍后使用那一信息,但是攻擊者可能會在這兩個步驟之間改變該情形。對文件系統來說,以下問題尤為突出;在這兩個步驟之間,攻擊者通常可以創建一個普通的文件或者一個符號鏈接。例如,如果某個已授予特權的程序檢查是否不存在給定名稱的文件,然后打開該文件寫入信息,那么在那兩個步驟之間,攻擊者可以創建一個使用該名稱的符號鏈接文件... 比如 /etc/passwd 或者其他一些敏感文件。 網絡的神奇作用吸引著越來越多的用戶加入其中,正因如此,網絡的承受能力也面臨著越來越嚴峻的考驗―從硬件上、軟件上、所用標準上......,各項技術都需要適時應勢,對應發展,這正是網絡迅速走向進步的催化劑。 |
溫馨提示:喜歡本站的話,請收藏一下本站!