2013-04-12 73 views
5

是否有(兼容)的方式來欺騙(作爲root)的Unix套接字(文件系統套接字)對等憑證其可以通過getsockopt()獲得,選項SO_PEERCREDUNIX套接字:是否有可能欺騙getsockopt()SO_PEERCRED?

背景:
我需要連接到服務器應用程序(我不能修改),其檢查其經由SO_PEERCRED連接到它的處理的UID。我想欺騙這些信息,以便能夠連接到應用程序作爲根,也可以

UPDATE

爲了澄清問題
我在尋找一種非侵入性的方式該服務器發現的特定對UID/GID。 解決方案是氣餒這就需要改變內核(或採取使用內核模塊的)或改變服務器進程或其裝載/以任何方式聯過程LD_PRELOAD,系統呼叫攔截等)。

基本上,解決方案應該在沒有任何特殊要求的任何linux(或一般unix)服務器上運行。服務器進程可能已經在運行。

+1

如果你是'root',爲什麼不只是'setuid'?你可以從一個完全控制的子進程中做到這一點,這樣你就可以避免實際上失去權限。 – nneonneo

+0

我不確定,但在Linux下,'/ proc//fdinfo/'中有一個八進制值前綴標誌。 – alk

+1

您可以控制服務器進程的啓動,即,您是否可以使用LD_PRELOAD修改庫函數/ syscall thunk來更改報告的憑據? –

回答

-1

不可以。原因是提供對等體的UID和GID的機制在內核內部爲,您無法欺騙內核!內核使用對等體的PID來推導對等體的有效憑證。當一方在插座上執行connect時會發生這種情況。請登錄net/unix/af_unix.c查看unix_stream_connect()的電話copy_peercred()。對等體無法改變它發送的數據或者說服內核說對等體的PID不是它的那個套接字。這與AF_INET套接字不同,內核沒有對等進程的內部知識,只能看到對等方發送的IP數據包頭中的數據。

您可以做的唯一的事情就是將對等進程的有效UID設置爲root或任何你想要的UID/GID,並且你需要root密碼或者sudo權限。

+1

但是你*可以*欺騙內核 - 作爲root用戶,你可以通過加載模塊來修改正在運行的內核的行爲。 –

+0

@ChrisStratton:你編寫的任何模塊都可以改變Unix域套接字的行爲。 –

+0

你是**嚴重**誤認爲相信。最簡單的方法是創建一個模塊,在進入內核後立即在調度點重定向系統調用,但修改unix域套接字實現的內部結構最終也是一種選擇。請記住,某些未導出的內容不受*保護*,它只是很難找到*,而且在源打開並且可能已知構建設置時並非如此。 –

3

你說得對。根進程有權欺騙這樣的事情,問題在於SO_PEERCRED沒有提供進程的機制或API來指定應該呈現給對等方的身份。

兩件事情可以做:

  1. 暫時放棄了root(setreuid(desired,-1))時,你的電話connect。在進程名爲connect(和listen以其他方式)時,unix域連接將標記對等方的憑證。 SO_PEERCRED不會告訴你當前對方的憑證。然後你可以恢復根目錄。

  2. 更好的是,使用另一個API。消息傳遞API允許進程選擇要向對等體呈現的標識。請致電sendmsg並使用struct cmsg包含要發送的憑據。內核將忽略非特權用戶指定的憑證,並始終確保對方看到實際身份,但特權進程可以假裝爲其他任何人。這更符合您的需求,因爲丟棄和重獲根源是一項危險的活動,在這種情況下是不必要的。 Google獲取「SCM_CREDENTIALS」(或者在您的系統上使用「man -K」)來獲取代碼示例。

+1

如果服務器未設置SO_PASSCRED套接字選項並讀取憑據,則解決方案2將不起作用。如果它只使用SO_PEERCRED,那麼你堅持使用簡單的一次性PID認證。有關SO_PEERCRED示例,請參閱http://man7.org/tlpi/code/online/dist/sockets/scm_cred_recv.c.html。無論如何,root用來使用SCM_CREDENTIALS來降低權限幾乎不是「欺騙」。 –

+1

好吧,叫它「模仿」,然後......另外,我似乎記得,如果你發送了一些證書,你不需要在另一端設置SO_PASSCRED;他們應該在'recvmsg'輸出中找到你。也許這是操作系統的依賴?我不傾向於使用Linux。 SO_PASSCRED通常用於當你想讀出憑證但另一方不寫他們;它會告訴內核爲每個消息提供對等憑證(對於DGRAM套接字來說特別好)。 –

+1

閱讀示例,「我們必須設置SO_PASSCRED套接字選項才能接收憑據」。 BSD/FreeBSD的選項稱爲SCM_CREDS也是如此。 –