天天看點

利用capability特征加強Linux系統安全

利用capability特征加強Linux系統安全

摘要:傳統UNIX系統的通路控制模型非常簡單--普通使用者對超級

使用者。在這種模型中,一個程序或者帳戶要麼隻有很小的權限,要麼具有全部的系統權限。顯然,這樣對系統的安全沒有什麼好處。從Linux-2.1核心開

始,引入了能力(capability)的概念,實作了更細粒度的通路控制。

    1.簡介

  UNIX是一種安全操

作系統,它給普通使用者盡可能低的權限,而把全部的系統權限賦予一個單一的帳戶--root。root帳戶用來管理系統、安裝軟體、管理帳戶、運作某些服

務、安裝/解除安裝檔案系統、管理使用者、安裝軟體等。另外,普通使用者的很多操作也需要root權限,這通過setuid實作。

  這種依

賴單一帳戶執行特權操作的方式加大了系統的面臨風險,而需要root權限的程式可能隻是為了一個單一的操作,例如:綁定到特權端口、打開一個隻有root

權限可以通路的檔案。某些程式可能有安全漏洞,而如果程式不是以root的權限運作,其存在的漏洞就不可能對系統造成什麼威脅。

  從2.1版開始,核心開發人員在Linux核心中加入了能力(capability)的概念。其目标是消除需要執行某些操作的程式對root帳戶的依賴。從2.2版本的核心開始,這些代基本可以使用了,雖然還存在一些問題,但是方向是正确的。

    2.Linux核心能力詳解

 

 傳統UNIX的信任狀模型非常簡單,就是“超級使用者對普通使用者”模型。在這種模型中,一個程序要麼什麼都能做,要麼幾乎什麼也不能做,這取決于程序的

UID。如果一個程序需要執行綁定到私有端口、加載/解除安裝核心子產品以及管理檔案系統等操作時,就需要完全的root權限。很顯然這樣做對系統安全存在很大

的威脅。UNIX系統中的SUID問題就是由這種信任狀模型造成的。例如,一個普通使用者需要使用ping指令。這是一個SUID指令,會以root的權限

運作。而實際上這個程式隻是需要RAW套接字建立必要ICMP資料包,除此之外的其它root權限對這個程式都是沒有必要的。如果程式編寫不好,就可能被

攻擊者利用,獲得系統的控制權。

  使用能力(capability)可以減小這種風險。系統管理者為了系統的安全可以剝奪root

使用者的能力,這樣即使root使用者也将無法進行某些操作。而這個過程又是不可逆的,也就是說如果一種能力被删除,除非重新啟動系統,否則即使root使用者

也無法重新添加被删除的能力。

    2.1.能力的概念

  Linux核心中使用的能力

(capability)概念非常容易被混淆。計算機科學中定義了很多種能力(capability)。能力就是一個程序能夠對某個對象進行的操作,它标

志對象以及允許在這個對象上進行的操作。檔案描述符就是一種能力,你使用open系統調用請求獲得讀或者寫的權限,如果open系統調用成功,系統的诤司

突峤�⒁桓鑫募枋龇H緩螅绻盞蕉粱蛘咝吹那肭螅诤司褪褂謎飧鑫募枋龇魑桓鍪萁峁溝乃饕焖飨喙氐牟僮魇欠裨市怼U馐且恢旨觳槿ㄏ薜撓

行Х絞劍谥蔥衞pen系統調用是,核心一次性建立必要的資料結構,然後的讀寫等操作檢查隻需要在資料結構中梭梭即可。對能力的操作包括:複制能力、程序

間的遷移能力、修改一個能力以及撤消一個能力等。修改一個能力類似與把一個可以讀寫的檔案描述符改為隻讀。目前,各種系統對能力的應用程度并不相同。

  POSIX 1003.1e中也提出了一種能力定義,通常稱為POSIX能力(POSIX capabilities),Linux中的定義不大一樣。核心使用這些能力分割root的權限,因為傳統*NIX系統中root的權限過于強大了。

    2.2.Linux是如何使用POSIX capabilities代替傳統的信任狀模型的

 每個程序有三個和能力有關的位圖:inheritable(I)、permitted(P)和effective(E),對應程序描述符

task_struct(include/linux/sched.h)裡面的cap_effective, cap_inheritable,

cap_permitted。每種能力由一位表示,1表示具有某種能力,0表示沒有。當一個程序要進行某個特權操作時,作業系統會檢查

cap_effective的對應位是否有效,而不再是檢查程序的有效UID是否為0。例如,如果一個程序要設定系統的時鐘,Linux的核心就會檢查

cap_effective的CAP_SYS_TIME位(第25位)是否有效,

  cap_permitted表示程序能夠使用的

能力。在cap_permitted中可以包含cap_effective中沒有的能力,這些能力是被程序自己臨時放棄的,也可以說

cap_effective是cap_permitted的一個子集。程序放棄沒有必要的能力對于提高安全性大有助益。例如,ping隻需要

CAP_NET_RAW,如果它放棄除這個能力之外的其它能力,即使存在安全缺陷,也不會對系統造成太大的損害。cap_inheritable表示能夠

被目前程序執行的程式繼承的能力。

    3.Linux支援的能力

  Linux實作了7個POSIX 1003.1e規定的能力,還有21個(截止到2.4.7-10版本的核心)Linux所特有的,這些能力在/usr/src/linux/include/linux/capability.h檔案中定義。其細節如下:

能力名 數字 描述  

CAP_CHOWN 0 允許改變檔案的所有權  

CAP_DAC_OVERRIDE 1 忽略對檔案的所有DAC通路限制  

CAP_DAC_READ_SEARCH 2 忽略所有對讀、搜尋操作的限制  

CAP_FOWNER 3 如果檔案屬于程序的UID,就取消對檔案的限制  

CAP_FSETID 4 允許設定setuid位  

CAP_KILL 5 允許對不屬于自己的程序發送信号  

CAP_SETGID 6 允許改變組ID  

CAP_SETUID 7 允許改變使用者ID  

CAP_SETPCAP 8 允許向其它程序轉移能力以及删除其它程序的任意能力  

CAP_LINUX_IMMUTABLE 9 允許修改檔案的不可修改(IMMUTABLE)和隻添加(APPEND-ONLY)屬性  

CAP_NET_BIND_SERVICE 10 允許綁定到小于1024的端口  

CAP_NET_BROADCAST 11 允許網絡廣播和多點傳播通路  

CAP_NET_ADMIN 12 允許執行網絡管理任務:接口、防火牆和路由等,詳情請參考/usr/src/linux/include/linux/capability.h檔案  

CAP_NET_RAW 13 允許使用原始(raw)套接字  

CAP_IPC_LOCK 14 允許鎖定共享記憶體片段  

CAP_IPC_OWNER 15 忽略IPC所有權檢查  

CAP_SYS_MODULE 16 插入和删除核心子產品  

CAP_SYS_RAWIO 17 允許對ioperm/iopl的通路  

CAP_SYS_CHROOT 18 允許使用chroot()系統調用  

CAP_SYS_PTRACE 19 允許跟蹤任何程序  

CAP_SYS_PACCT 20 允許配置程序記帳(process accounting)  

CAP_SYS_ADMIN 21 允許執行系統管理任務:加載/解除安裝檔案系統、設定磁盤配額、開/關交換裝置和檔案等。詳情請參考/usr/src/linux/include/linux/capability.h檔案。  

CAP_SYS_BOOT 22 允許重新啟動系統  

CAP_SYS_NICE 23 允許提升優先級,設定其它程序的優先級  

CAP_SYS_RESOURCE 24 忽略資源限制  

CAP_SYS_TIME 25 允許改變系統時鐘  

CAP_SYS_TTY_CONFIG 26 允許配置TTY裝置  

CAP_MKNOD 27 允許使用mknod()系統調用  

CAP_LEASE 28 Allow taking of leases on files  

    4.能力邊界集

 Linux2.2核心提供了對能力的基本支援。但是在引入了能力之後遇到了一些困難,雖然2.2版本的核心能夠了解能力,但是缺乏一個系統和使用者之間的

接口。除此之外,還存在其它的一些問題。從2.2.11版本開始,這種情況發生了很大的改觀,在這個版本中引入了能力邊界集(capability

bounding set)的概念,解決了和系統和使用者之間的接口問題。能力邊界集(capability bounding

set)是系統中所有程序允許保留的能力。如果在能力邊界集中不存在某個能力,那麼系統中的所有程序都沒有這個能力,即使以超級使用者權限執行的程序也一

樣。

  能力邊界集通過sysctl指令導出,使用者可以在/proc/sys/kernel/cap-bound中看到系統保留的能力。在預設情況下,能力邊界集所有的位都是打開的。

  root使用者可以向能力邊界集中寫入新的值來修改系統保留的能力。但是要注意,root使用者能夠從能力邊界集中删除能力,卻不能再恢複被删除的能力,隻有init程序能夠添加能力。通常,一個能力如果從能力邊界集中被删除,隻有系統重新啟動才能恢複。

 删除系統中多餘的能力對提高系統的安全性是很有好處的。假設你有一台重要的伺服器,比較擔心可加載核心子產品的安全性。而你又不想完全禁止在系統中使用可

加載核心子產品或者一些裝置的驅動就是一些核心子產品。在這種情況下,最好使系統在啟動時加載所有的子產品,然後禁止加載/解除安裝任何核心子產品。在Linux系統

中,加載/解除安裝核心子產品是由CAP_SYS_MODULE能力控制的。如果把CAP_SYS_MODULE從能力邊界集中删除,系統将不再允許加載/解除安裝

任何的核心子產品。

  CAP_SYS_MODULE能力的值是16,是以我們使用下面的指令就可以把它從能力邊界集中删除:

  echo 0xFFFEFFFF >/proc/sys/kernel/cap-bound

    5.lcap

[root@nixe0n lcap-0.0.6]# ./lcap

Current capabilities: 0xFFFFFEFF

   0) *CAP_CHOWN                   1) *CAP_DAC_OVERRIDE         

   2) *CAP_DAC_READ_SEARCH         3) *CAP_FOWNER               

   4) *CAP_FSETID                  5) *CAP_KILL                 

   6) *CAP_SETGID                  7) *CAP_SETUID               

   8)  CAP_SETPCAP                 9) *CAP_LINUX_IMMUTABLE      

  10) *CAP_NET_BIND_SERVICE       11) *CAP_NET_BROADCAST        

  12) *CAP_NET_ADMIN              13) *CAP_NET_RAW              

  14) *CAP_IPC_LOCK               15) *CAP_IPC_OWNER            

  16) *CAP_SYS_MODULE             17) *CAP_SYS_RAWIO            

  18) *CAP_SYS_CHROOT             19) *CAP_SYS_PTRACE           

  20) *CAP_SYS_PACCT              21) *CAP_SYS_ADMIN            

  22) *CAP_SYS_BOOT               23) *CAP_SYS_NICE            

  24) *CAP_SYS_RESOURCE           25) *CAP_SYS_TIME            

  26) *CAP_SYS_TTY_CONFIG      

    * = Capabilities currently allowed

  如果我們需要删除某個能力,直接把能力名作為參數就可以,例如我們要删除加載/解除安裝核心子產品的能力:

[root@nixe0n lcap-0.0.6]# ./lcap CAP_SYS_MODULE

Current capabilities: 0xFFFBFEFF

  16)  CAP_SYS_MODULE             17) *CAP_SYS_RAWIO            

    6.能力邊界集的安全問題

 能力邊界集為系統和管理者之間提供了一個便利的互動接口,但是它存在一些的脆弱性。Patrick

Reynolds在送出到BugTraq的一個郵件裡詳細分析了這種脆弱性。對能力邊界集的最大威脅就是能夠被讀/寫的/dev/mem裝置。在核心記憶體

區中,/proc/sys/kernel/cap-bound直接影射到cap_bset變量中。如果/dev/mem可以寫,攻擊者就能夠直接修改記憶體

重置cap_bset變量。進而能夠越過能力邊界集打開所有的能力。使用以下指令就可以獲得cap_bset變量的位址:

$ grep cap_bset System.map

c01f0cd5 ? __kstrtab_cap_bset

c01f7340 ? __ksymtab_cap_bset

c01fb2ac D cap_bset

  從結果可以看出,cap_bset位于c01fb2ac。攻擊者獲得了/dev/mem的寫權限,隻要寫入0xffffffff就能夠重新打開所有的能力。

 是以,為了維護能力邊界集的安全,你應該放棄系統的CAP_SYS_RAWIO能力。這樣會造成X系統和其它一些需要通路/dev/mem或I/O端口

的程式無法運作,不過對于伺服器來說,這是值得的。除了關閉CAP_SYS_RAWIO,還應該放棄CAP_SYS_MODULE能力。

    7.局限

 雖然利用能力可已經以有效地保護系統的安全,但是由于檔案系統的制約,Linux的能力控制還不是很完善。我們除了可以使用lcap從總體上放棄一些能

力之外,伺服器軟體程式員也應該主動放棄程序的一些多餘的能力。例如,xntpd程式可以通過以下的步驟放棄沒有必要的能力,以加強安全性:

以完整的root權限啟動

綁定到ntp端口

除了CAP_SYS_TIME能力之外,放棄其它的能力

放棄root權限

以普通管理帳戶的身份進行正常的操作

  但是,并不是所有的程式員能夠注意到這個問題,如果能夠直接使用chmod和chattr指令限制程式的能力将給為友善。例如:

[root@localhost /root]# chattr +CAP_BIND xntpd

  目前,由于檔案系統的制約,還無法實作。

    8.結論

  在本文,我們讨論了Linux的能力,并說明了如何使用相關的工具加強系統的安全性。但是,能力還守制于檔案系統的擴充,并不是非常完善。

繼續閱讀