歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
Linux教程網 >> Linux編程 >> Linux編程 >> Linux沙箱(1): setuid sandbox

Linux沙箱(1): setuid sandbox

日期:2017/3/1 9:33:38   编辑:Linux編程

Setuid Sandbox主要是基於Linux Kernel所提供的安全機制(eg,DAC)來實現。簡單地說就是利用 random uid/gid + chroot() + capability的組合出擊來達到目標。其實現非常簡單,無需修改Kernel。下面分別悉數之:

1. Linux中每個進程都會有一個uid,uid=0則為root用戶進程(privileged),uid>0則為普通用戶進程(unprivileged)。不同uid進程之間(不包括root進程)是相互隔離的,各自都有自己獨立的權限,互不干擾。而root進程具有特權,它能干任何事情。Linux uid/gid機制主要是用於進程的權限隔離。如果你打算執行不可信的程序,那麼你可以在啟動該程序時為其分配一個random uid。一個可能的執行流程如下:fork() -> setuid() -> {設置相關的進程資源限制, eg, RLIMIT_NPROC (0,0)} -> execv()。注意,setuid()只能由root權限(或擁有 CAP_SETUID capability)才能成功調用,所以這個執行流程需要借助某個擁有root權限的helper。比如,將helper程序設置為setuid root。

2. Chroot是Linux kernel提供的另一個安全功能,它用於修改進程的根目錄。比如執行chroot("/tmp/sandbox/1/")則可以設置當前進程的根目錄為"/tmp/sandbox/1/",那麼該進程的文件操作將被限制在"/tmp/sandbox/1/"中。注意,chroot()只能由root權限(或擁有CAP_SYS_CHROOT capability)才能成功調用。也許你馬上會想到:在前面的執行流程中,先讓具有root權限的helper去執行"chroot()"後再調用setuid() -> {...} -> execve(),但這樣做是行不通的,因為execve()本要執行的binary文件已經不可用了(進程的根目錄已經被重定位了)。Google的一篇文章裡給出了一個解決此問題的簡單方法:

(1) Helper創建一個子進程H,注意要用clone()和CLONE_FS,使得Helper和H可以共享根目錄、當前目錄、等等;

(2) Helper降權後執行execve("Worker");

(3) Worker(原Helper進程)請求H去執行chroot();

(4) H執行chroot(),新的根目錄會對H和Worker同時生效。

(5) H退出。

這個方法聽起來不錯,前提是Helper需要設置RLIMIT_NOFILE為(0,0),並且對於不可信的Worker進程來說,在執行第4步之前應是可控的。

另外,對於Helper程序來說,由於它是以root身份運行,那麼就可能會成為攻擊點,比如confused deputy問題。下面我們介紹如何用capability機制來解這個問題。

3. Linux Capability 主要是解決 confused deputy problem. 這類問題的典型代表之一是 CSRF(cross-site request forgery).給一個簡單的例子來描述: 假如你剛剛用浏覽器訪問過你的網上銀行,而同時又在逛水木BBS。這時BBS上的某個壞蛋可能正好猜到你在訪問網上銀行,於是那個壞蛋就編寫一個在你的網上銀行站點進行轉帳的form提交的鏈接,並將該鏈接作為他在BBS上傳的圖片的tag。如果此時你點擊了他的圖片,並且你的網上銀行在cookie中保存的授權信息還沒有過期,那麼你就倒霉了。此時的你就被稱為"confused deputy",因為你糊裡糊塗地就授權了那個壞蛋所誘導的這次交易事務。

Linux支持Capability的主要目的是細化root的特權,以避免confused deputy problem. 比如拿ping程序來說,它需要使用raw_sockets所以需要root特權才能運行;如果有了Capability機制,由於該程序只需要一個CAP_NET_RAW的Capability即可運行,那麼根據最小權限原則,該程序運行時可以丟棄所有多余的Capability,以防止被誤用或被攻擊。所以,Capability機制可以將root特權進行很好的細分,當前kernel(2.6.18)已支持30多種不同的Capability。注意在之前的kernel實現中,Capability只能由root進程持有,非root進程是不能保持任何Capability的。但是在2.6.24及以上的kernel版本中一個普通用戶進程也將可以持有capability。

小結:可以看出,setuid sandbox實現是簡單易行。在一定程度上,它可以用於隔離不可信的程序。由於它完全依賴於kernel所提供的安全機制,除非攻擊者能找到kernel的0-day漏洞並通過攻擊獲得root權限,否則setuid sandbox所提供的安全隔離是可以保證的。不可信代碼的隔離一直都是操作系統安全領域的挑戰之一,面對這種挑戰,我們應當采用防御縱深(in depth)的方法來解決。而最近,我們發現setuid sandbox已被Google用作Chromium系統的第一道隔離屏障。

Copyright © Linux教程網 All Rights Reserved