Chroot

如果我的應用程序從一開始就可以在較低級別執行,我為什麼要 chroot 進行沙盒以確保安全?

  • June 2, 2018

我正在用 C 語言編寫一個 HTTP 伺服器守護程序(這是有原因的),並使用 systemd 單元文件對其進行管理。

我正在重寫一個 20 年前設計的應用程序,大約在 1995 年。他們使用的系統是 chroot,然後是 setuid,以及標準程序。

現在,在我之前的工作中,通常的政策是您永遠不會以 root 身份執行任何程序。您為它創建一個使用者/組並從那裡執行。當然,系統確實以root身份執行了一些東西,但我們可以不以root身份完成所有業務邏輯處理。

現在對於 HTTP 守護程序,如果我不在應用程序中 chroot,我可以在沒有 root 的情況下執行它。那麼,應用程序永遠不會以 root 身份執行不是更安全嗎?

從一開始就以 mydaemon-user 身份執行它不是更安全嗎?而不是從 root 啟動它,chrooting,然後 setuid 到 mydaemon-user?

似乎其他人錯過了你的觀點,這不是為什麼要使用變根的原因,當然你已經清楚地知道了,也不是你可以做些什麼來限制守護程序,當你也清楚地知道在非特權使用者帳戶;但是為什麼要在應用程序內部做這些事情。實際上有一個相當恰當的例子來說明原因。

考慮httpdDaniel J. Bernstein 的 publicfile 包中守護程序的設計。它所做的第一件事是將 root 更改為它被告知要與命令參數一起使用的根目錄,然後將權限刪除到在兩個環境變數中傳遞的非特權使用者 ID 和組 ID。

Dæmon 管理工具集具有專用工具,用於更改根目錄和刪除非特權使用者和組 ID。Gerrit Pape 的 runit 有chpst. 我的 nosh 工具集有chrootsetuidgid-fromenv. Laurent Bercot 的 s6 有s6-chroots6-setuidgid. 韋恩·馬歇爾 (Wayne Marshall) 的 Perp 有runtoolrunuid. 等等。事實上,他們都有 M. Bernstein 自己的 daemontools 工具集setuidgid作為先行詞。

人們會認為可以從httpd這些專用工具中提取功能並使用它們。然後,正如您所設想的,伺服器程序的任何部分都不會以超級使用者權限執行。

問題是,一個直接後果是必須做更多的工作來設置更改的根,這會暴露出新的問題。

就Bernstein而言httpd,根目錄樹中唯一的文件和目錄是要發佈到世界各地的文件和目錄。樹上什麼都沒有。此外,任何可執行程序映像文件都沒有理由存在於該樹中。

但是將根目錄更改為鍊式載入程序(或 systemd),然後突然將程序映像文件httpd,它載入的任何共享庫,以及程序載入器或 C 執行時庫訪問的任何特殊文件/etc/run以及/dev在程序初始化期間(如果您truss/strace是 C 或 C++ 程序,您可能會發現這非常令人驚訝),必須存在於更改的根目錄中。否則httpd無法連結到並且不會載入/執行。

請記住,這是一個 HTTP(S) 內容伺服器。它可能會在更改的根目錄中提供任何(世界可讀的)文件。這現在包括您的共享庫、程序載入器以及作業系統的各種載入器/CRTL 配置文件的副本。如果某些(意外)意味著內容伺服器有權寫入內容,則受感染的伺服器可能會獲得對httpd自身程序映像的寫入權限,甚至是您系統的程序載入器。(請記住,您現在有兩組平行的/usr/lib/etc/run/dev目錄來保證安全。)

這些都不是httpd更改 root 並自行刪除特權的情況。

因此,您已經換取了少量特權程式碼,這些程式碼相當容易審計,並且在httpd程序開始時執行,以超級使用者權限執行;因為在更改的根目錄中具有極大擴展的文件和目錄的攻擊面。

這就是為什麼它不像在服務程序外部做所有事情那麼簡單。

請注意,這仍然是其自身的最低限度的功能httpd。所有執行操作的程式碼,例如在作業系統的帳戶數據庫中查找使用者 ID 和組 ID 以首先放入這些環境變數中,都是程序外部的httpd,在簡單的獨立可審計命令中,例如envuidgid. (當然,它是一個 UCSPI 工具,因此它不包含任何用於偵聽相關 TCP 埠或接受連接的程式碼,這些程式碼是諸如tcpservertcp-socket-listentcp-socket-accepts6-tcpserver4-socketbinder、等命令的域s6-tcpserver4d。)

進一步閱讀

引用自:https://unix.stackexchange.com/questions/447305