首先,setuid()
絕對可以被非超級用戶使用。從技術上講,您在Linux中所需的全部是切換到任何用戶的CAP_SETUID
(和/或CAP_SETGID
)capability。其次,setuid()
和setgid()
可以更改真實(執行過程的用戶),有效(所有者setuid/setgid二進制)和保存的身份之間的進程標識。
但是,這些都與您的情況無關。
存在一個相對直接但非常健壯的解決方案:在創建任何線程之前,有一個setuid根助手,由服務守護程序分叉並執行,並使用Unix域套接字對在助手和服務之間進行通信,當要執行用戶二進制文件時,該服務將其憑證和管道端點文件描述符傳遞給幫助程序。該幫助程序將安全地檢查所有內容,如果所有內容都符合要求,它將分叉並執行所需的用戶幫助程序,並將指定的管道端點連接到標準輸入,標準輸出和標準錯誤。
用於啓動輔助,儘可能早地將服務的過程,如下:
創建Unix域socket pair,用於服務和輔助之間特權的通信。
叉。
在孩子中,關閉所有多餘的文件描述符,只保留套接字對的一端。將標準輸入,輸出和錯誤重定向到/dev/null
。
在父項中,關閉套接字對的子端。
在孩子中,執行特權助手二進制。
父母發送一個簡單的消息,可能是一個沒有任何數據的消息,但是包含其憑據的ancillary message。
幫助程序等待來自該服務的初始消息。 當它收到它時,它會檢查憑證。如果證書不通過,它立即退出。
輔助消息中的證書定義始發過程UID
,GID
,和PID
。儘管進程需要填寫這些內核,但內核證實它們是真實的。當然,該幫助程序驗證UID
和GID
是否如預期的那樣(對應於該服務應該運行的帳戶),但訣竅是獲取符號鏈接指向的文件統計信息/proc/PID/exe
。這是發送證書的過程的真正可執行文件。您應該驗證它與安裝的系統服務守護程序(由root:root擁有,位於系統二進制目錄中)相同。
有一個非常簡單的攻擊可能會破壞安全到目前爲止。惡意用戶可能會創建自己的程序,它會正確分叉並執行助手二進制文件,併發送帶有其真實憑據的初始消息 - 但在助手有機會檢查憑據實際引用的內容之前,用自己的正確系統二進制文件替換它本身!
那攻擊平凡三個進一步的步驟擊敗:
助手程序產生(密碼安全)的僞隨機數,說1024位,並將其發送回父。
父母發回數字,但又在輔助消息中添加憑證。
助手程序驗證UID
,GID
和PID
沒有改變,那/proc/PID/exe
仍然指向正確的服務守護程序二進制文件。 (我只是重複全程把關。)
在步驟8,助手已經確定了插座的另一端執行的二進制它應該被執行。發送它必須發送回來的隨機cookie,意味着另一端不能事先用消息「填充」套接字。當然,這假設攻擊者無法事先猜出僞隨機數。如果你想要小心,你可以從/dev/random
中讀取一個合適的cookie,但記住它是一個有限的資源(如果內核沒有足夠的隨機性可能會阻塞)。我個人只是讀從/dev/urandom
說1024位(128字節),並使用它。
此時,助手已經確定套接字對的另一端是服務守護進程,並且幫助者可以信任控制消息,只要它可以信任服務守護進程即可。 (我假設這是服務守護進程產生用戶進程的唯一機制;否則,你需要在每一個進一步的消息中重新傳遞憑證,並且每次在助手中重新檢查它們。)
每當服務守護程序希望執行用戶二進制,它
創建必要的管道(一個用於饋送標準輸入到用戶的二進制,一個取回來自用戶的二進制標準輸出)
將消息發送到包含
- 身份到作爲運行的二進制輔助;任一用戶(和組)名稱,或UID和GID(S)
- 路徑提供給二進制
- 含有文件描述符的用戶的二進制端點的輔助信息的二進制
- 命令行參數數據管道
每當輔助得到這樣的消息,它叉子。在子代中,它將標準輸入和輸出替換爲輔助消息中的文件描述符,將標識更改爲setresgid()
和setresuid()
和/或initgroups()
,將工作目錄更改爲適當的某處並執行用戶二進制文件。父助手進程關閉輔助消息中的文件描述符,並等待下一條消息。
如果輔助程序在沒有更多來自套接字的輸入時退出,那麼它將在服務退出時自動退出。
我可以提供一些示例代碼,如果有足夠的興趣。有很多細節可以正確使用,所以編寫代碼有點乏味。然而,正確書寫,它比例如Apache SuEXEC。
您可以將'root'切換爲非特權用戶,然後在需要時切換回(通過[已保存的用戶標識](http://en.wikipedia.org/wiki/User_identifier#Saved_user_ID)機制)切換到不同的用戶。 –
嗯,我不認爲這會增加我的情況下的任何安全性,假設切換回機制不受保護。所以如果主要服務被利用,直到root纔會是一個微不足道的額外步驟。 – Jeroen
這取決於你「被剝削」的含義。如果你的意思是他們可以讓它訪問他們想要的任何代碼,那麼我認爲這是最基本的。他們可以添加代碼來記錄它用來切換用戶的憑證,然後使用這些憑證來利用系統。除非你的意思是根特別會受到影響。 –