20199317 2019-2020-2 《網路攻防實踐》綜合實踐
PeX: A Permission Check Analysis Framework for Linux Kernel
一. 介紹
-
PeX: Linux核心的許可權檢查分析框架,這篇論文來自
usenix security 2019
。 -
許可權檢查通過為特權功能提供訪問控制,從而在作業系統安全性中發揮重要作用。然而,對於核心開發人員來說,正確地應用新的許可權檢查並可伸縮地驗證現有檢查的可靠性是特別具有挑戰性的,這是由於核心的程式碼基數大且複雜。
-
這篇論文介紹了一個用於Linux核心的靜態許可權檢查框架PeX:
○ PeX可以很好地、可伸縮地檢測出核心程式碼中任何丟失的、不一致的和冗餘的許可權檢查。從高層次上講, PeX靜態地探索從使用者入口點(例如,系統呼叫)到特權函式的所有可能的程式路徑,並且檢測出其中的錯誤。
○ 以一組已知的許可權檢查作為輸入,自動識別出所有其他的許可權檢查(包括他們的包裝器) -
本文的貢獻總結如下:
○ 新技術:我們提出並實現了PeX,一個用於Linux核心的靜態許可權檢查分析框架。我們還開發了新的技術,可以執行可伸縮的間接呼叫分析,並自動識別許可權檢查和特權函式的過程。
○ 實際影響:我們使用 PeX 分析了最新Linux核心v4.18.5中的DAC
、Capabilities
和LSM
許可權檢查,發現了36個新的許可權檢查錯誤,其中14個已經被核心開發人員確認。
○ 社群貢獻:我們將以開源專案的形式釋出PeX,同時釋出的還有已確定的許可權檢查和特權函式之間的對映。這將允許核心開發人員使用PeX驗證他們的程式碼,並使用他們自己的領域改進對映,從而為PeX做出貢獻。
二. 背景:Linux中的許可權檢查
2.1 自主訪問控制(DAC)
-
DAC根據主體的身份或它們所屬的組來限制對關鍵資源的訪問。在Linux中, 為每個使用者分配一一個使用者識別符號(uid)和一個組識別符號(gid)。 相應地,每個檔案都有其屬性,包括所有者、組,以及所有者、組和所有其他使用者的rwx(讀、寫和執行)許可權位。當一個程序想要訪問一個檔案時,DAC根據程序的uid、gid以及檔案的許可權位授予訪問許可權。
-
在某種意義上,DAC是一種粗粒度的訪問控制模型。在這種Linux DAC的設計下,"root"繞過所有的許可權檢查。
2.2 Capabilities
-
自Linux核心2.2(1999)以來,Capabilities 通過將根特權劃分為小集合來支援細粒度的訪問控制。例如,對於具有CAP NET ADMIN能力的使用者,核心允許他們使用ping,而不需要授予完全的root特權。
-
CAP應該是細粒度的、不同的。然而,由於缺乏明確的範圍定義,保護一個特權函式的特定Capabilities的選擇是基於核心開發人員在實踐中的理解而做出的。不幸的是,這就導致了CAP_SYS_ADMIN 的頻繁使用(1167中有451個,超過38%),並且它只是作為另一個根處理; grsecurity指出, 有19個Capabilities確實相當於完整的根。
2.3 Linux 安全模組
-
LSM是在核心v2.6 (2003) 中引入的,它提供了一組細粒度的可插入鉤子, 這些鉤子被放置在核心的各個安全臨界點上。系統管理員可以向LSM鉤子註冊自定義的許可權檢查回撥,從而執行不同的安全策略。
-
LSM的一個常見用途是在Linux中實現強制訪問控制 (MAC) (例如, SELinux ,AppArmor) : 例如,當一個程序試圖讀取一個符號連結的檔案路徑時,將呼叫security_inode_readlink來檢查這個程序是否具有對符號連結檔案的讀許可權。這個鉤子的SELinux回撥檢查是否有策略規則可以授予這個許可權(例如,允許
domain_atype. b:lnk_file_read
)。 -
值得注意的是:LSM及其MAC機制的有效性在很大程度上取決於鉤子是否在所有的安全臨界點上正確地放置。如果一個鉤子在任何臨界點丟失,MAC就沒有辦法強制執行許可權檢查。
2.4 Linux中常用的許可權檢查
三. 許可權檢查錯誤的例子
3.1 Capabilities許可權檢查錯誤
- 分析:圖a顯示了核心函式
scsi_ioctl
, 其中sg_scsi_ioctl
(第7行)由兩個 Capabilities 檢查保護,CAP_SYS_ADMIN
和CAP_SYS_RAWIO
(第5行);
- 分析:圖b中,
scsi_cmd_ioctl
呼叫了函式sg_scsi_ioctl
(第8行),但是沒有任何的Capabilities檢查;
-
分析:圖c中,
sg_scsi_ioctl
呼叫blk_verify_command
,後者反過來檢查CAP_SYS_RAWIO
; -
綜上所述,
scsi_ioctl
檢查了CAP_SYS_ADMIN
一次,但是檢查了CAP_SYS_RAWIO
兩次,導致了一次多餘的許可權檢查。另一方面,scsi_cmd_ioctl
只檢查CAP_SYS_RAWIO
,造成缺少對CAP_SYS_ADMIN
的許可權檢查。 -
總結:PeX將上面的錯誤檢測為不一致的許可權檢查,因為這兩條路徑不一致,進一步的研究表明,其中一條路徑是冗餘的,而另一條是缺失的。
3.2 LSM許可權檢查錯誤
- 分析:圖a顯示了在
readlinkat
系統呼叫中LSM的使用。在它的呼叫路徑上,vfs_readlink
(第7行)受到LSM鉤子security_inode_readlink
(第4行)的保護。
-
分析:圖b給出了系統呼叫
ioctl
的兩個子函式。loctl
呼叫ksys_ioctl
, 它在do_vfs_ioctl
(第6行)之前包含它自己的LSM鉤子security_file_ioctl
(第4行)。然後,從do_vfs_ioctl
到xfs_readlink_by_ handle
(第10行)有一條路徑,最終呼叫特權函式vfs_readlink
(參見圖a中的第7行和圖b中的第13行)。雖然vfs_readlink
受到readlinkat
中的LSM鉤子security_inode_readlink
的保護,但是通過xfs_readlink_by_handle
的函式的路徑卻不是這樣。 -
問題是SELinux為
read
和ioctl
保留了單獨的“允許”規則。當缺少LSMsecurity_inode_readlink
檢查,只具有"ioctl allow rule"
的使用者可以利用ioctl
系統呼叫來觸發vfs_readlink
操作,而這樣的操作應該只會被不同的"read allow rule"
所允許。
四. 挑戰
4.1 核心中間接呼叫分析
-
第一個關鍵挑戰是linux核心中間接呼叫的頻繁使用,以及以可伸縮的、精確的方式靜態分析間接呼叫的困難。
為了實現模組化設計,核心提出了一組不同的抽象層,這些抽象層指定了不同具體模組的公共介面。例如虛擬檔案系統(VFS),抽象了一個檔案系統,從而提供了一種統一的、透明的方式來訪問本地(例如ext4)和網路(例如nfs)儲存裝置。
在這個核心程式設計正規化下,一個抽象層將一個介面定義為一組間接函式指標,而一個具體模組則用自己的實現來初始化這些指標。 -
核心龐大的程式碼基數使得對核心介面中大量函式指標的解析成為一個挑戰性問題,這也使得現有的精確指標分析技術不可伸縮。而SVF,這種使用流和上下文敏感值流的高精度先進分析技術,也不能運用到龐大的Linux核心中去。
基於型別這種簡單的函式指標分析技術雖然能夠運用到Linux核心中,但是由於在核心中的函式指標通常共享相同的型別,從而導致很多的錯誤定位,基於型別的間接分析的精確度也就不高。
4.2 缺乏完整的許可權檢查、特權函式及其對映
- 第二個挑戰是在Linux中健全地列舉出一組許可權檢查,並推斷出許可權檢查和特權函式之間的對映。
雖然已知一些常用的DAC
、Capabilities
和LSM
許可權檢查,但是核心開發人員經常設計一些在內部使用基本許可權檢查的自定義許可權檢查(包裝程式)。然而,此類許可權檢查的完整列表從沒被記錄下來。而且,Linux核心沒有明確指定哪個許可權檢查應該保護哪個特權函式的文件。現有的靜態許可權錯誤檢查技術並不適用於解決這些問題。
五. PeX的設計
5.1 PeX的靜態分析結構
-
PeX以核心原始碼和許可權檢查作為輸入,報告並輸出許可權檢查錯誤。PeX還在已識別的許可權檢查和特權函式之間生成對映,作為輸出。
-
下面根據這個結構進行具體分析。
5.2 KIRIN 間接呼叫分析
5.2.1 間接呼叫目標收集
-
在Linux核心中,一個核心介面通常是在由函式指標組成的C結構中定義的。很多核心介面(C結構)靜態地被分配和初始化。一些介面可以在執行時動態地分配和初始化以進行重新配置。
-
對於前者,KIRIN線性地掃描所有Linux核心程式碼,找到所有被靜態分配和初始化的帶有函式指標欄位的
struct
物件。然後,對於每個struct
物件,KIRIN 使用偏移量作為欄位的鍵值來跟蹤哪個函式地址被分配給哪個函式指標欄位。 -
對於其餘動態初始化的核心介面,KIRIN 在核心介面中執行一個數據流分析,以收集一個函式地址到函式指標的任何分配。KIRIN的欄位敏感分析允許收集目標與核心介面的單個欄位相關聯。
5.2.2 間接呼叫站點解析
-
KIRIN 將前邊第一次傳遞的結果儲存在
key——value
對映資料結構中,其中key
是一對核心介面型別和一個偏移量(欄位),value
是一組呼叫目標。在每個間接呼叫站點中,KIRIN 從LLVM IR
中檢索出核心介面的型別和偏移量,使用它們作為key
以查詢對映,並計算出匹配的呼叫目標。 -
當把KIRIN應用於Linux核心時,我們發現在某些呼叫站點中,核心介面型別並沒有出現在
LLVM IR
中,這就使得對它們的解析變得不可能。例如,巨集container_of
通常用於通過使用指向自身成員欄位的指標來獲取結構物件的起始地址。
5.3 呼叫圖的產生和分割槽
-
使用者空間可訪問函式:從帶有公共字首
SyS_
(表明系統呼叫入口點)的函式開始,PeX遍歷呼叫圖,標記所有訪問過的函式,並將這些函式視為使用者空間可訪問函式。研究此分割槽中使用者可訪問的函式是否存在許可權檢查錯誤。 -
核心初始化函式:收集僅在啟動期間使用的函式,以探測冗餘檢查。Linux 核心從
start_kernel
函式啟動,呼叫一個使用通用字首_init
的函式列表。PeX 從start_kernel
和每一個_init
函式開始,執行多個呼叫圖遍歷,去收集這些函式。 -
其他函式,如IRQ處理程式和核心執行緒函式,由於不能直接從使用者空間呼叫,在以後的分析中不會用到。
5.4 許可權檢查包裝器檢測
-
PeX將使用者提供的不完整的許可權檢查列表作為輸入。從這些許可權檢查開始,PeX通過在擴張的呼叫圖上執行正向呼叫圖切片來檢測基本的許可權檢查。對於一個給定的許可權檢查函式,PeX搜尋函式內的所有呼叫指令,查詢將函式的引數傳遞給被呼叫函式的指令。換句話說,PeX標識出了許可權檢查函式的各個被呼叫函式,這些被呼叫函式將其實際引數作為它們自己的形式引數。類似地,PeX 然後從這些基本許可權檢查中執行向後呼叫圖切片,以檢測出其包裝器的列表。PeX 僅將那些傳遞許可權引數的呼叫函式看作包裝器,不包括其他僅使用許可權檢查的呼叫函式。
-
如下為每次檢測時許可權檢查包裝器的示例:給定一個已知的許可權檢查
ns_capable
(第10-13行),PeX首先找到security_capable
(第4行)作為一個基本的許可權檢查,然後基於它,PeX檢測出另一個許可權檢查包裝器has_ns_capability
(第14-20行)。注意,引數cap
從父節點ns_capable_common
和has_ns_capability
傳遞給子節點security_capable
;返回security_capable
的結果。
5.5 特權函式檢測
-
PeX利用了一個過程間控制分析,該分析可以自動識別被一個給定許可權檢查保護的特權函式。PeX 適當地將那些呼叫指令的所有目標(被呼叫函式),即在ICFG的基礎上的每個許可權檢查所控制的目標(被呼叫函式),當作其潛在的特權函式。
-
控制分析的基本原理是基於以下觀察結果:由於沒有一條路徑允許不訪問控制者就可以訪問控制呼叫指令(即許可權檢查),所以被呼叫函式的情況很有可能是它在所有路徑上應該被檢查保護著。
-
特權函式檢測演算法:
5.6 非特權函式過濾器
-
PeX應用基於啟發式的過濾器來刪減錯誤的特權函式。在當前的原型中,過濾器包含了一組不是特權函式的核心庫函式,例如,
kmalloc
、strcmp
、kstrtoint
. -
PeX目前的設計是為了避免假陰性(因此只利用了一小組庫過濾器),但是可以新增更具攻擊性的過濾器來清除更多錯誤的特權函式。
5.6 特權函式錯誤檢測
六. 實現與評估
6.1 KIRIN 的評估
- 解析率: K-Miner 只能解析間接呼叫站點的1%;只能用於
defconfig
, 不用於allyesconfig
. - 解析的平均目標:對於KIRIN來說,每個已解析的間接呼叫站點的平均間接呼叫目標數比基於型別的方法要少得多。
- 分析時間:基於型別的方法是最快的,可以在1分鐘內完成對兩種配置的分析。KIRIN的執行速度比基於型別的方法慢。但是,對於
defconfig
, KIRIN的分析時間 (≈1分鐘)與基於型別方法的分析時間相當,而KIRIN對allyesconfig
的分析時間為6.6分鐘。基於SVF的K-Miner完成對defconfig的所有系統呼叫的分析大約需要9869分鐘,比KIRIN慢得多。
6.2 PeX的結果
- 使用不同的間接呼叫分析時PeX警告的比較:
○ 對於allyesconfig,PeX+TYPE
和PeX+KM
在12小時的實驗限制內無法完成分析。PeX+TYPE
在ICFG中產生了太多的(假)邊,在PeX分析的最後階段還發生了路徑爆炸;在超時之前,只報告了19個bug。同時,PeX+KM
在較早的指標分析階段就已經出現超時,因此無法報告任何錯誤。
○ 對於defconfig,PeX+TYPE
和PeX+KM
都能夠完成分析。在這個配置下,PeX+KIRIN (original)
和PeX+ TYPE
都報告了21個bug (是allyesconfig
檢測到的36個bug中的一個子集)。PeX+ KM產生有限數量的警告,導致只檢測到6個bug,其餘的都沒有發現。
6.3 PeX報告的Bug
七. 論文復現
-
實驗環境:
實驗平臺:Ubuntu 16.04,kernel v4.18,LLVM-6/7/8/9
原始碼下載:https://github.com/lzto/pex
LLVM下載及配置:https://github.com/travitch/whole-program-llvm
-
DAC下產生的許可權檢查錯誤日誌檔案:
-
CAP下產生的許可權檢查錯誤日誌檔案:
-
LSM下產生的許可權檢查錯誤日誌檔案:
八. 總結與心得
-
通過這門課的學習,我由衷地開始敬佩那些黑客們,以前對黑客的印象只是停留在電影裡,很是虛幻,而我現在對黑客的感覺就是——大神大神大神!!!能夠被稱為黑客,本身就說明其具有極高的專業技能。還有就是以前總以為黑客就是破壞網路世界、損害國家社會及他人利益的代名詞,而這門課的課本從一開始就澄清了“黑客”這個詞的概念,它是有黑帽子白帽子灰帽子之分的,“黑帽子”才是對社會帶來負面作用的駭客,“白帽子”則是對社會積極作用的黑客,並且白帽子的存在對於網路世界的安全具有極大的價值和意義,正是有了這些白帽子,才得以抵禦黑帽子的入侵與破壞,保證國家社會網路生活的正常進行。
-
從搭建網路攻防的實驗環境到網路踩點收集有效資訊,再到後邊每次實踐都會用到多種工具,一步步深入到最後能夠遠端控制受害者主機以及植入後門方便下次攻擊,最後的綜合實踐也是給了我們認真看論文學習怎麼看論文的機會,還是收穫很多的。
-
學習必須與實踐相結合,知識如果不加以實踐,終究是紙上談兵,一到應用階段就潰不成軍,實踐能夠加深我們對於知識的理解,加強我們的動手能力,培養我們的動手能力以及獨立思考的能力,這些對於我來說還是很有價值的。另外,通過這門課的學習,我也深深感到網路世界的危險性,個人隱私保護的重要性,以及安全意識的培養對於每一個公民的重大意義。
-
從寒假開始的寒假作業,一直到最後的綜合實踐,難度是越來越大,我也從一開始的能夠跟得上課程到後邊一次一次跟不上,每次作業完成都只能參考同學的部落格才可以完成,而且對於每次的實踐作業也是似懂非懂,最後的綜合實踐也是好難好難好難。