LWN:Fedora 和 pkexec!

語言: CN / TW / HK

關注了就能看到更多這麼棒的文章哦~

Fedora and pkexec

By Jake Edge February 2, 2022 DeepL assisted translation https://lwn.net/Articles/883547/ 

pkexec 中那個煩人的漏洞已經在 Linux 世界中激起了漣漪,引出了對底層 polkit 授權工具包(authorization toolkit)的大量安全更新。它也引出了最近在 Fedora 開發郵件列表中關於 pkexec(用來以另一個使用者的身份執行程式)是否真的有必要、或者說是否在某些或所有發行版中有必要的討論。但是 pkexec 被許多不同的 Fedora 元件所使用,尤其是在桌面版本 Fedora 中,在需要以另一個使用者的許可權執行程式時,它也許是一個比其他選項更好的選擇。

Adam Williamson 在 PwnKit 漏洞披露的第二天提出了這個問題。正如他所指出的,這是一個長期存在的(從 2009 年第一個版 pkexec 開始)本地 root 許可權升級問題。這讓他開始思考:

這個問題和周圍的一些評論,促使我想知道——為什麼 `pkexec'仍然有必要存在?尤其是,為什麼它仍然是我們在每一個 Fedora 安裝中都預設使用的東西?

我的印象中,pkexec 是一個讓我們擺脫 consolehelper 的笨辦法:一些應用沒有被改寫成在 policykit 下的正確方式,他們仍然希望整個應用以 root 身份執行,而 pkexec 是實現這一目的的一種方法。

consolehelper 是另外一個允許使用者以其他使用者身份執行程式碼的程式,而 PolicyKit 是 polkit 的舊稱。2013 年的時候,Fedora Usermode Migration 這個功能的設計目標就是將 consolehelper 的所有使用者者都轉移到 polkit。Williamson 想知道,當前的 Fedora 中有哪些部分仍然需要 pkexec(畢竟其更像是一個拼湊的用法)。但是,由於它被包含在 polkit 軟體包中,而 polkit 的使用非常廣泛,也許可以把 pkexec 分割成一個 sub-package,只在真正需要它的地方安裝,這是他的建議。

在後續的討論中,Williamson 指出,根據 Usermode migration 的 bug ticket 看來它還沒有完成。Fedora 中仍有 15 個軟體包需要 consolehelper。Peter Robinson 說,其中大部分 "似乎是歷史遺留" 軟體包,沒有再被普遍使用了。

Michael J Gruber 開玩笑地問,他是否應該把他的軟體包從 pkexec 切換到使用基於 consolehelper 的 beesu 包裝過的 su 命令上去,因為 beesu 在 Fedora 中仍然存在。但 Williamson 說他可不建議這麼做:

並不是說 pkexec 在本質上比任何其他做差不多的事情(也就是提示輸入某個密碼,然後以 root 身份執行整個應用程式)的工具更糟糕。不幸的是 pkexec 碰巧有一個巨大的安全缺陷,但如果有人決定仔細檢查進去的話,其他做同樣事情的工具沒準也有安全缺陷。問題是,*整個設計* 就不是最優的。

他說,我們的想法是,應該讓應用程式轉而使用 polkit 提供的其他機制,以進行他們的特權操作。對於那些不進行這種改變的應用程式來說,pkexec 是一個 "不那麼好的第二選擇",可以讓它們能繼續工作。刪除 consolehelper 是為了減少發行版需要注意的 "以 root 身份執行命令" 的工具的總數,儘管這還沒有完全完成。"從 pkexec 切換到其他任何 '以 root 身份執行東西'的工具都不能算是改進。"

如果你無論如何都要以 root 身份執行程式, pkexec 可能比使用 sudo 或其他選項更好,Lennart Poettering 認為。pkexec 已經使用 polkit 程序間通訊(IPC)機制來請求以 root 身份執行二進位制檔案,這在他看來是一個優越的模式:

我的意思是,polkit 有一些問題,但我非常肯定,"pkexec" 本身我認為並不是大問題。或者換個說法:像 su/sudo/setpriv/runuser/suid binaries 這些工具的整個理念才是[有問題的]:也就是說,我非常肯定,如果我們能系統地禁止通過 execve() 獲得許可權,而把重點放在把許可權操作委託給 IPC 服務上,我們會過得更好——當然,這種做法與傳統 UNIX 相比有很大區別。

[…] "pkexec "是一個 短小 的程式,它實際上只運行了很少的特權程式碼。這使得它比 "sudo" 這個[巨大的]程式碼怪物要好上許多倍。它有一個更小的 安全規模(security footprint),而且比 "sudo" 更容易 review。這實際上是很有價值的。

但是 Sam Varshavchik 反對這樣的觀點,他不認為把特權操作轉移到 IPC 機制(比如 socket)的另一端,真的會解決什麼根本問題。當前的問題是,一些以 root 身份執行的程式有 bug:

在 suid[也就是 setuid]二進位制檔案中可被利用的 bug,如果出現在等價的無 suid 的程式中,也同樣可以被利用,攻擊方式完全相同。如果你在 suid 二進位制檔案中由於精心設計的命令列引數或環境變數而導致緩衝區溢位,那麼如果你用一個相同的 bug-for-bug 實現來替換 suid 二進位制檔案,使用 socket 來仔細傳遞相同的環境變數或引數給本地 root 許可權的二進位制程式,並且產生相同的緩衝區溢位,那麼你猜怎麼著:你仍然有相同的漏洞。

suid 不是問題所在。execve 執行的程式將繼承環境變數以及開啟的檔案描述符,也許還有一些其他的東西,而一個接受 socket 連線的獨立 daemon 程式是沒有這些東西的。但這些是大多數漏洞利用的東西,所以清理掉環境變數和已開啟的檔案描述符可以彌補這個漏洞。要利用其他內容的話,攻擊者就需要更加費力了。

然而,Poettering 並不這樣看。在執行 setuid 二進位制檔案時,會有大量的狀態變化,而且這些狀態會隨著時間的推移而增加:

setuid/setgid 的問題在於,被呼叫的特權程序繼承了很多隱含的狀態和上下文,而人們並沒有真正意識到、或完全理解這些狀態和上下文。也就是說,它不僅僅是 env vars 和 argv[],還包括 cgroup membership、audit fields 欄位、security context 安全上下文、開啟的 fds、子程序 pids、父程序 pids、cpu mask、IO/CPU 排程優先順序、各種 prctl()設定、tty 控制、signal mask+handler,…等等。甚至不清楚什麼會被繼承下來,因為程序一直在不斷增加更多的屬性。

如果你通過 IPC 來對特定的操作進行特權執行,你就會得到保證,無論做什麼,都是在一個定義良好的、原始的執行環境中完成的,不會隱性地洩露上下文。IPC 訊息是 全部的 脆弱攻擊面了,這是我們能做到的最小的攻擊面。這很好。

Varshavchik 說,雖然所有這些上下文和狀態都存在於 setuid 程式中,但根本問題是在程式本身:

而這些都沒有任何區別,除非程式碼本身也有一個潛在的邏輯錯誤。而這將是真正的問題。那麼,問題就來了,有多少漏洞利用了這些特別的資源,比如 cgroup members、tty control 以及所有其他那些不被注意的屬性?我想可能有幾個,但我想不起來了。另一方面,完成 execve("/bin/bash") 的漏洞也同樣有效,因為 root 守護程序中有同樣的潛在 bug,可以通過其前端或 suid 程式觸發。一個經過消毒的環境不會有什麼幫助。

但對於 setuid 程式來說,完全淨化環境是很難或不可能做到的,Poettering 說。有許多相互互動的屬性是由 setuid 二進位制程式的呼叫者(也就是攻擊者)控制的,而且這個數字還在不斷增加:

你可能*希望*沒有通過所有這些程式碼的互動引入錯誤,但我想說的是,"struct task "和核心中的相關物件一直在被擴充套件,而那些沒有預料到這些新增物的 suid 程式將被暴露在其中,而且即使他們想重置它們,也不能理智地重置,因為通常開發人員不能展望未來(而且 cgroup 的東西甚至根本不能合理地重置)。

Varshavchik 想拿到一些資料依據,來證明這裡設想的各種漏洞的情況。他和 Poettering 來回討論了一陣有什麼算是合適的資料,但沒有真正達成一致。Poettering 在結束他對這個子話題的參與時指出,他可以理解 "你對 suid 和 sudo 的熱愛",但他和其他人認為它們是 "一個非常糟糕的主意"。Varshavchik 認為他並不是對這些機制感到著迷:

我說不上喜歡或者不喜歡 suid + sudo,就跟我喜歡我的螺絲刀差不多。我對這兩者都不感冒。兩者都只是工具。兩者都可以被人們正確使用。兩者也都可以被人們以錯誤的方式使用。但是,並不會因為這一點而用扳手來替代螺絲刀。

Demi Marie Obenour 建議,被一個 setuid 二進位制檔案繼承哪些狀態資訊,應該由該二進位制檔案來選擇。"狀態的繼承絕對應該是精心選擇過的,但某些 audit 資料可能例外,如 audit user ID"。從事 Linux audit 系統開發工作的 Steve Grubb 說,audit 依賴於二進位制檔案繼承 security context 和 audit 資訊,所以現有的 polkit 機制是不夠的。如果採用 kdbus 這樣的核心機制,那麼這個問題就可以避免了。就目前的情況來看,polkit "不能滿足我們的安全要求":

[……]因為 policy 是千變萬化的 javascript, 而不是一些可以被什麼掃描程式來檢查的一些固定配置,所以無法確定應該允許哪些狀態,拒絕哪些狀態。而且決定是否能訪問,也並不經過 audit 系統。因此,我們對那些使用了 IPC 啟動的應用程式,很少能瞭解它的訪問控制以及資訊流情況。 
Setuid 可能對某些人來說是很令人討厭的。但它的屬性是眾所周知的,完全可以對平臺提供一定程度的保證。 

他並不是唯一一個抱怨 polkit 的 JavaScript 配置機制的人,因為這被許多人看作是一個糟糕的設計決策。同時,Andrew Lutomirski 說,實現一個核心內的 IPC 機制是很困難的問題。他對 setuid 也有一些想法:

我希望在 Linux 核心中看到一個很好的 IPC 安全模型,但我還沒有見過可靠的提案出來。這個問題是 非常難的

至於 setuid,我強烈認為 setuid 無論是在過去和現在都是一個錯誤。執行一個程序不應該增加許可權。

回到他最初的主題,Williamson 指出,這個話題的討論已經很清楚地表明,目前至少有一些 Fedora 的桌面版之類的釋出(spin)需要 pkexec,不過:"這不是一個容易回答的問題,因為我們的打包系統並沒有區分哪些東西需要 polkit 哪些東西需要  pkexec 。" Fedora 專案負責人 Matthew Miller 認為這至少是可以修改的:"我想,第一步可能是把 pkexec 拆成一個 subpackage,然後逐漸消滅對它的依賴。"

這就是目前為止的所有情況了。把 pkexec 拿出來它打包,似乎是一個好的計劃,不管它是否應該慢慢地從實際使用中移除出去。如果出現另一個漏洞,也會更加容易地追查哪些其他 package 在使用它。長期來說,轉向更多的或完全是 polkit 式的許可權提升功能可能不一定會實現。在這條道路上的共識尚未完全弄清楚,而且這也是一個發行版中不希望看到大量改動的領域,至少不太會有很多程式碼 review。

就像大多數(所有?)漏洞一樣,真正的罪魁禍首是缺乏對程式碼的集中安全審查(focused security review)。對於 setuid 二進位制檔案以及其他那些以 root 身份執行的程式碼來說,review 應該是必須的,但目前還不清楚是否有大量密集的 review 正在進行。每當另一個影響廣泛的漏洞出現時,我們就會被提醒,但相關的影響似乎很快都會消失,事情又恢復了 "正常"。這是一個相當令人擔憂的狀態。

全文完

LWN 文章遵循 CC BY-SA 4.0 許可協議。

歡迎分享、轉載及基於現有協議再創作~

長按下面二維碼關注,關注 LWN 深度文章以及開源社群的各種新近言論~