1.簡介
UNIX是一種安全操作系統(tǒng),它給普通用戶盡可能低的權(quán)限,而把全部的系統(tǒng)權(quán)限賦予一個(gè)單一的帳戶--root。root帳戶用來管理系統(tǒng)、安裝軟件、管理帳戶、運(yùn)行某些服務(wù)、安裝/卸載文件系統(tǒng)、管理用戶、安裝軟件等。另外,普通用戶的很多操作也需要root權(quán)限,這通過setuid實(shí)現(xiàn)。
這種依賴單一帳戶執(zhí)行特權(quán)操作的方式加大了系統(tǒng)的面臨風(fēng)險(xiǎn),而需要root權(quán)限的程序可能只是為了一個(gè)單一的操作,例如:綁定到特權(quán)端口、打開一個(gè)只有root權(quán)限可以訪問的文件。某些程序可能有安全漏洞,而如果程序不是以root的權(quán)限運(yùn)行,其存在的漏洞就不可能對系統(tǒng)造成什么威脅。
從2.1版開始,內(nèi)核開發(fā)人員在Linux內(nèi)核中加入了能力(capability)的概念。其目標(biāo)是消除需要執(zhí)行某些操作的程序?qū)oot帳戶的依賴。從2.2版本的內(nèi)核開始,這些代基本可以使用了,雖然還存在一些問題,但是方向是正確的。
2.Linux內(nèi)核能力詳解
傳統(tǒng)UNIX的信任狀模型非常簡單,就是“超級用戶對普通用戶”模型。在這種模型中,一個(gè)進(jìn)程要么什么都能做,要么幾乎什么也不能做,這取決于進(jìn)程的UID。如果一個(gè)進(jìn)程需要執(zhí)行綁定到私有端口、加載/卸載內(nèi)核模塊以及管理文件系統(tǒng)等操作時(shí),就需要完全的root權(quán)限。很顯然這樣做對系統(tǒng)安全存在很大的威脅。UNIX系統(tǒng)中的SUID問題就是由這種信任狀模型造成的。例如,一個(gè)普通用戶需要使用ping命令。這是一個(gè)SUID命令,會(huì)以root的權(quán)限運(yùn)行。而實(shí)際上這個(gè)程序只是需要RAW套接字建立必要ICMP數(shù)據(jù)包,除此之外的其它root權(quán)限對這個(gè)程序都是沒有必要的。如果程序編寫不好,就可能被攻擊者利用,獲得系統(tǒng)的控制權(quán)。
使用能力(capability)可以減小這種風(fēng)險(xiǎn)。系統(tǒng)管理員為了系統(tǒng)的安全可以剝奪root用戶的能力,這樣即使root用戶也將無法進(jìn)行某些操作。而這個(gè)過程又是不可逆的,也就是說如果一種能力被刪除,除非重新啟動(dòng)系統(tǒng),否則即使root用戶也無法重新添加被刪除的能力。
2.1.能力的概念
Linux內(nèi)核中使用的能力(capability)概念非常容易被混淆。計(jì)算機(jī)科學(xué)中定義了很多種能力(capability)。能力就是一個(gè)進(jìn)程能夠?qū)δ硞€(gè)對象進(jìn)行的操作,它標(biāo)志對象以及允許在這個(gè)對象上進(jìn)行的操作。文件描述符就是一種能力,你使用open系統(tǒng)調(diào)用請求獲得讀或者寫的權(quán)限,如果open系統(tǒng)調(diào)用成功,系統(tǒng)的內(nèi)核就會(huì)建立一個(gè)文件描述符。然后,如果收到讀或者寫的請求,內(nèi)核就使用這個(gè)文件描述符作為一個(gè)數(shù)據(jù)結(jié)構(gòu)的索引,檢索相關(guān)的操作是否允許。這是一種檢查權(quán)限的有效方式,在執(zhí)行open系統(tǒng)調(diào)用是,內(nèi)核一次性建立必要的數(shù)據(jù)結(jié)構(gòu),然后的讀寫等操作檢查只需要在數(shù)據(jù)結(jié)構(gòu)中梭梭即可。對能力的操作包括:復(fù)制能力、進(jìn)程間的遷移能力、修改一個(gè)能力以及撤消一個(gè)能力等。修改一個(gè)能力類似與把一個(gè)可以讀寫的文件描述符改為只讀。目前,各種系統(tǒng)對能力的應(yīng)用程度并不相同。
POSIX 1003.1e中也提出了一種能力定義,通常稱為POSIX能力(POSIX capabilities),Linux中的定義不大一樣。內(nèi)核使用這些能力分割root的權(quán)限,因?yàn)閭鹘y(tǒng)*NIX系統(tǒng)中root的權(quán)限過于強(qiáng)大了。
2.2.Linux是如何使用POSIX capabilities代替?zhèn)鹘y(tǒng)的信任狀模型的
每個(gè)進(jìn)程有三個(gè)和能力有關(guān)的位圖:inheritable(I)、permitted(P)和effective(E),對應(yīng)進(jìn)程描述符task_struct(include/linux/sched.h)里面的cap_effective, cap_inheritable, cap_permitted。每種能力由一位表示,1表示具有某種能力,0表示沒有。當(dāng)一個(gè)進(jìn)程要進(jìn)行某個(gè)特權(quán)操作時(shí),操作系統(tǒng)會(huì)檢查cap_effective的對應(yīng)位是否有效,而不再是檢查進(jìn)程的有效UID是否為0。例如,如果一個(gè)進(jìn)程要設(shè)置系統(tǒng)的時(shí)鐘,Linux的內(nèi)核就會(huì)檢查cap_effective的CAP_SYS_TIME位(第25位)是否有效,
cap_permitted表示進(jìn)程能夠使用的能力。在cap_permitted中可以包含cap_effective中沒有的能力,這些能力是被進(jìn)程自己臨時(shí)放棄的,也可以說cap_effective是cap_permitted的一個(gè)子集。進(jìn)程放棄沒有必要的能力對于提高安全性大有助益。例如,ping只需要CAP_NET_RAW,如果它放棄除這個(gè)能力之外的其它能力,即使存在安全缺陷,也不會(huì)對系統(tǒng)造成太大的損害。cap_inheritable表示能夠被當(dāng)前進(jìn)程執(zhí)行的程序繼承的能力。
3.Linux支持的能力
Linux實(shí)現(xiàn)了7個(gè)POSIX 1003.1e規(guī)定的能力,還有21個(gè)(截止到2.4.7-10版本的內(nèi)核)Linux所特有的,這些能力在/usr/src/linux/include/linux/capability.h文件中定義。其細(xì)節(jié)如下:
能力名 數(shù)字 描述
CAP_CHOWN 0 允許改變文件的所有權(quán)
CAP_DAC_OVERRIDE 1 忽略對文件的所有DAC訪問限制
CAP_DAC_READ_SEARCH 2 忽略所有對讀、搜索操作的限制
CAP_FOWNER 3 如果文件屬于進(jìn)程的UID,就取消對文件的限制
CAP_FSETID 4 允許設(shè)置setuid位
CAP_KILL 5 允許對不屬于自己的進(jìn)程發(fā)送信號(hào)
CAP_SETGID 6 允許改變組ID
CAP_SETUID 7 允許改變用戶ID
CAP_SETPCAP 8 允許向其它進(jìn)程轉(zhuǎn)移能力以及刪除其它進(jìn)程的任意能力
CAP_LINUX_IMMUTABLE 9 允許修改文件的不可修改(IMMUTABLE)和只添加(APPEND-ONLY)屬性
CAP_NET_BIND_SERVICE 10 允許綁定到小于1024的端口
CAP_NET_BROADCAST 11 允許網(wǎng)絡(luò)廣播和多播訪問
CAP_NET_ADMIN 12 允許執(zhí)行網(wǎng)絡(luò)管理任務(wù):接口、防火墻和路由等,詳情請參考/usr/src/linux/include/linux/capability.h文件
CAP_NET_RAW 13 允許使用原始(raw)套接字
CAP_IPC_LOCK 14 允許鎖定共享內(nèi)存片段
CAP_IPC_OWNER 15 忽略IPC所有權(quán)檢查
CAP_SYS_MODULE 16 插入和刪除內(nèi)核模塊
CAP_SYS_RAWIO 17 允許對ioperm/iopl的訪問
CAP_SYS_CHROOT 18 允許使用chroot()系統(tǒng)調(diào)用
CAP_SYS_PTRACE 19 允許跟蹤任何進(jìn)程
CAP_SYS_PACCT 20 允許配置進(jìn)程記帳(process accounting)
CAP_SYS_ADMIN 21 允許執(zhí)行系統(tǒng)管理任務(wù):加載/卸載文件系統(tǒng)、設(shè)置磁盤配額、開/關(guān)交換設(shè)備和文件等。詳情請參考/usr/src/linux/include/linux/capability.h文件。
CAP_SYS_BOOT 22 允許重新啟動(dòng)系統(tǒng)
CAP_SYS_NICE 23 允許提升優(yōu)先級,設(shè)置其它進(jìn)程的優(yōu)先級
CAP_SYS_RESOURCE 24 忽略資源限制
CAP_SYS_TIME 25 允許改變系統(tǒng)時(shí)鐘
CAP_SYS_TTY_CONFIG 26 允許配置TTY設(shè)備
CAP_MKNOD 27 允許使用mknod()系統(tǒng)調(diào)用
CAP_LEASE 28 Allow taking of leases on files
4.能力邊界集
Linux2.2內(nèi)核提供了對能力的基本支持。但是在引入了能力之后遇到了一些困難,雖然2.2版本的內(nèi)核能夠理解能力,但是缺乏一個(gè)系統(tǒng)和用戶之間的接口。除此之外,還存在其它的一些問題。從2.2.11版本開始,這種情況發(fā)生了很大的改觀,在這個(gè)版本中引入了能力邊界集(capability bounding set)的概念,解決了和系統(tǒng)和用戶之間的接口問題。能力邊界集(capability bounding set)是系統(tǒng)中所有進(jìn)程允許保留的能力。如果在能力邊界集中不存在某個(gè)能力,那么系統(tǒng)中的所有進(jìn)程都沒有這個(gè)能力,即使以超級用戶權(quán)限執(zhí)行的進(jìn)程也一樣。
能力邊界集通過sysctl命令導(dǎo)出,用戶可以在/proc/sys/kernel/cap-bound中看到系統(tǒng)保留的能力。在默認(rèn)情況下,能力邊界集所有的位都是打開的。
root用戶可以向能力邊界集中寫入新的值來修改系統(tǒng)保留的能力。但是要注意,root用戶能夠從能力邊界集中刪除能力,卻不能再恢復(fù)被刪除的能力,只有init進(jìn)程能夠添加能力。通常,一個(gè)能力如果從能力邊界集中被刪除,只有系統(tǒng)重新啟動(dòng)才能恢復(fù)。
刪除系統(tǒng)中多余的能力對提高系統(tǒng)的安全性是很有好處的。假設(shè)你有一臺(tái)重要的服務(wù)器,比較擔(dān)心可加載內(nèi)核模塊的安全性。而你又不想完全禁止在系統(tǒng)中使用可加載內(nèi)核模塊或者一些設(shè)備的驅(qū)動(dòng)就是一些內(nèi)核模塊。在這種情況下,最好使系統(tǒng)在啟動(dòng)時(shí)加載所有的模塊,然后禁止加載/卸載任何內(nèi)核模塊。在Linux系統(tǒng)中,加載/卸載內(nèi)核模塊是由CAP_SYS_MODULE能力控制的。如果把CAP_SYS_MODULE從能力邊界集中刪除,系統(tǒng)將不再允許加載/卸載任何的內(nèi)核模塊。
CAP_SYS_MODULE能力的值是16,因此我們使用下面的命令就可以把它從能力邊界集中刪除:
echo 0xFFFEFFFF >/proc/sys/kernel/cap-bound
5.lcap
雖然我們可以直接修改/proc/sys/kernel/cap-bound來刪除系統(tǒng)的某中能力,但是這樣畢竟非常的不方便。有一個(gè)程序lcap可以幫助我們更方便的從系統(tǒng)中刪除指定的能力。它可以從http://home.netcom.com/~spoon/lcap/下載。編譯之后就可以直接使用。如果不帶參數(shù),lcap可以列出系統(tǒng)當(dāng)前支持的各種能力:
|