網絡技術是從1990年代中期發展起來的新技術,它把互聯網上分散的資源融為有機整體,實現資源的全面共享和有機協作,使人們能夠透明地使用資源的整體能力并按需獲取信息。資源包括高性能計算機、存儲資源、數據資源、信息資源、知識資源、專家資源、大型數據庫、網絡、傳感器等。 當前的互聯網只限于信息共享,網絡則被認為是互聯網發展的第三階段。 共享目錄的解決方案 不幸的是,有很多并不是解決方案。有一些程序只是直接調用 mktemp(3) 或 tmpnam(3) 來創建臨時文件,然后基于這樣做會成功的假定去簡單地打開它。錯誤的計劃!實際上,線程使用 tmpnam(3) 并不可靠,也不能可靠地處理循環,所以永遠不要使用它。1997 年的“Single Unix Specification”推薦使用 tmpfile(3),但不幸的是,在一些老系統上實現它很不安全。 在 C 中,為了在共享(sticky)目錄中安全地創建臨時文件,通常的解決方案是將 umask() 值設置為一個非常受限制的值,然后反復進行以下操作:(1)創建一個“隨機的”文件名,(2)使用 O_CREAT | O_EXCL 選項 open(2) 它(這將自動創建文件,如果沒有創建該文件,則操作失。,(3)當成功打開文件時停止重復步驟。 C 程序員實際上不需要直接這樣去做;只需要調用庫函數 mkstemp(3),就可以打開文件。mkstemp(3) 的一些實現并沒有將 umask(2) 設置為一個受限的值,所以聰明的做法是先調用 umask(2) 來強制將文件設置為受限的值。有一個小麻煩,mkstemp(3) 不直接支持 TMP 或 TMPDIR 環境變量,所以,如果這對您來說是重要的,那么您必須做更多的工作。 當為了安全地打開臨時文件而在共享(臨時)目錄中創建文件系統對象時,GNOME 編程向導推薦您使用下面的 C 代碼: 清單 3. 推薦使用的創建臨時文件的 C 代碼 char *filename; int fd; do { filename = tempnam (NULL, "foo"); fd = open (filename, O_CREAT | O_EXCL | O_TRUNC | O_RDWR, 0600); free (filename); } while (fd == -1); 注意,盡管使用了不安全的 tempnam(3) 函數,但是它被包裝在循環中,并使用了 O_CREAT 和 O_EXCL 選項,從而抵消了它的安全弱點,所以這樣做是可以的。一個附帶好處是,tempnam(3) 通常使用 TMPDIR,這使得用戶可以重定向其臨時文件,如果需要的話。注意,您需要 free() 文件名稱。完成使用之后,您應該 close() 并 unlink() 文件。這種方法有一個小的缺點,由于可能無法安全使用 tempnam,所以各種編譯器和安全掃描器可能都會向您發出使用不合邏輯的警告。使用 mkstemp(3) 就不存在這個問題。 整個這個打開文件的方法展示出了標準的 C IO 庫的一個奇特之處:沒有標準的方法來指定 O_EXCL 選項使用 fopen(),所以您不能以“普通的” C 方式來打開文件,并安全地創建臨時文件。如果您想使用標準 C IO 庫,然后使用 open(),那么您可以使用指定“w+b” 模式的 fdopen(),將文件描述符轉換為一個 FILE *。 Perl 程序員應該使用 File::Temp,它嘗試提供一個安全創建臨時文件的跨平臺方法。不過,首先要仔細閱讀如何正確使用它的文檔;它同樣有不安全的函數接口。我建議您顯式地將 safe_level 設置為 HIGH;這樣就會調用附加的安全檢查。對大部分編程庫來說都是如此;大部分庫都既有安全接口,又有不安全接口,所以您需要查閱文檔,并確保選擇了安全的版本。 注意,在舊版的 NFS(版本 1 或者版本 2)的目錄上使用 O_EXCL 是沒有用的,因為 NFS 的這些舊版本沒有正確地支持 O_EXCL。如果您自己使用了 O_EXCL,而且共享目錄是使用這些舊版 NFS 實現的,那么您的程序將是不安全的。實際上,關于舊版 NFS 中 link(2) 和 stat(2) 的使用有一個復雜的解決方法;如果您的程序一定要在這樣的環境中工作,那么您可以在 Linux 的 open(2)手冊頁或者其他地方閱讀關于該方法的內容。在這里我不準備對它進行討論,因為即使您的程序可以與舊版的 NFS 一起使用,您所使用的很多其他程序也不會使用該解決方法。無論如何您都不可能獲得使用 NFS 版本 1 或者版本 2 的臨時目錄的安全系統,因為其他程序沒有使用該解決方法,所以,如果使用遠程掛載的臨時目錄,更明智的做法是要求使用 NFS 版本 3 或更高版本。 您可以嘗試使用 mkdtemp(3),但這通常不是一個好主意,因為臨時文件清除器(temp cleaners)可能會決定清除它們。 如果您正在編寫 shell 腳本,那么可以使用管道,或者在用戶的主目錄存入臨時文件。根本不要使用 /tmp 或 /var/tmp 目錄;普通的 shell 通常無法支持文件描述符,所以臨時文件清除器(tmpfile cleaners)最終將使它們失敗。如果沒有臨時文件清除器,而且您只是必須在 /tmp 中創建臨時文件,那么至少要使用 mktemp(1) 來防止更明顯的攻擊,因為 mktemp(1)(不是 mktemp(3))將使用 O_EXCL 來防止典型的競爭條件攻擊。您可能做的最糟糕事情通常也是最令人不安的事:假定“$$”沒有被攻擊者猜出來,并且只是將信息重定向到這類文件;那么在創建時就不會按要求使用 O_EXCL 模式。攻擊者可以簡單地預創建類似的文件,或者反復創建和刪除它們,最終接管程序。這樣,類似的 shell 腳本幾乎肯定有一個嚴重的缺陷: 清單 4. 有缺陷的 shell 腳本 echo "This is a test" > /tmp/test$$ # DON'T DO THIS. 不要再次使用臨時文件名稱(即不要刪除和重新創建文件),不管您最初是如何獲得“安全的”臨時文件名稱。攻擊者都有可能觀察到原始的文件名稱,并在您第二次重新創建它時非法控制它。當然,要始終使用合適的文件權限。 做好自己的清理工作,或者通過使用退出處理器,或者利用 UNIX 文件系統語義,在創建后立即 unlink() 該文件,以便在清除目錄條目的同時仍然可以訪問該文件,直到指向它的最后一個文件描述符被關閉。于是,您就可以在自己的程序中通過傳送文件描述符來訪問該文件。對代碼維護來說,解除文件的鏈接有很多好處:不管您的程序是怎樣崩潰的,文件都會被自動刪除。它還降低了維護者不安全地使用文件名的可能性(改為使用文件描述符)。立即解除鏈接也有一個小問題,即這使得管理員查看磁盤空間使用情況的難度稍有增加。 使這些對策成為操作系統的一部分已經取得了一些成功,盡管它們當前還沒有被廣為使用。要獲得更多資料,請參閱參考資料列表中關于來自 OpenWall 項目的 Solar Designer 的 Linux 內核補丁、RaceGuard,以及 Eugene Tsyrklevich 和 Bennet Yee 的工作鏈接。 網絡的神奇作用吸引著越來越多的用戶加入其中,正因如此,網絡的承受能力也面臨著越來越嚴峻的考驗―從硬件上、軟件上、所用標準上......,各項技術都需要適時應勢,對應發展,這正是網絡迅速走向進步的催化劑。 |
溫馨提示:喜歡本站的話,請收藏一下本站!