Theo de Raadt 提議在 OpenBSD 中加入一種新機制來縮小攻擊面,該機制透過擴展 openat 系統呼叫來實現。目前已為核心、libc 庫以及基礎系統中的一些應用程式準備了補丁,這些補丁為 openat 和 open 添加了額外的標誌,限制了透過「/.」導航到上層目錄以及存取絕對路徑的能力。這些變更尚未合併到 OpenBSD-current 中,目前仍在開發者之間討論中。
openat(2) 系列系統呼叫與 open(2) 的行為類似,差異在於如果「path」參數是相對路徑,則要開啟的檔案相對於與檔案描述子「fd」關聯的目錄,而不是目前工作目錄。例如,如果您將絕對路徑傳遞給 openat,則:int dirfd = open("/tmp", O_RDONLY | O_DIRECTORY); int hfd = openat(dirfd, "/etc/hosts", O_RDONLY);
openat() 函數會忽略“dirfd”,因此絕對路徑將正常處理。
因此,用 openat() 取代 open() 本身並不能提高程式安全性。此呼叫可能會加快路徑解析速度,但不會限制對檔案系統的存取。禁止使用絕對路徑的標誌(例如,openat2 的 RESOLVE_BENEATH 和/或 RESOLVE_IN_ROOT) Linux):程式設計師必須將它們新增到所有適當的呼叫中,並且在取得進程控制權時,攻擊者可以使用其他方式開啟檔案。
在開發 openrsync 工具時,Theo 需要限制其檔案系統遍歷能力,但使用 reveal() 和 pledge() 函數無法實現這一點。於是,他構思了一種類似 openat() 的機制,但增加了安全特性,可以與 pledge/unveil 函數互補,甚至在缺少這些函數的情況下也能正常運作。
基本想法是將限制條件直接融入目錄描述符本身。為此,我們建議使用 F_BELOW 標誌(可透過 fcntl() 設定)或 O_BELOW 標誌(用於 open() 函數)。受此限制的「dirfd」描述符將僅允許向下遍歷目錄樹:使用絕對路徑的 openat() 呼叫或透過「..」向上遍歷目錄樹的操作將失敗並傳回 ENOENT 錯誤。當發生程式碼執行攻擊時,進程的檔案描述符表中功能正常的「dirfd」描述符數量將減少,從而縮小攻擊面。
來源: opennet.ru
