歡迎光臨
每天分享高質量文章

LINUX漏洞緩解機制介紹

一.應用層安全防護

1.ASLR

ASLR(Address space layout randomization,地址空間佈局隨機化)通過隨機放置資料區域的地址空間來防止攻擊者跳轉到記憶體的特定位置。在windows上ASLR主要包括堆棧隨機化、PEB與TEB隨機化、映像隨機化,windows系統上雖然xp時代就提出來了,但是從vista開始ASLR才真正發揮作用。在linux上ASLR主要包括棧地址隨機化、LIBS/MMAP隨機化、EXEC隨機化、BRK隨機化、VDSO隨機化。在沒有ASLR的情況下讓程式跳轉到一個已經存在的系統函式的漏洞利用方式被稱為ret2libc。

1.1 棧地址隨機化: 2.6.15內核開始支持。

1.2 LIBS/MMAP隨機化: 程式每次執行動態庫都被加載到不同的記憶體位置。2.6.15內核開始支持。

1.3 EXEC隨機化: 程式每次執行都將加載到不同的記憶體位置。2.6.25內核開始支持(會在第二點Built as PIE中詳細討論)。

可以這麼理解,LIBS/MMAP隨機化相當於windows中dll的隨機化,而EXEC隨機化相當於windows中exe的隨機化。

1.4 BRK隨機化: linux系統中brk和mmap這兩個系統呼叫用來分配記憶體。當brk ASLR關閉的時候,start_brk和brk都是指向bss段的尾部的;當brk ASLR開啟的時候,start_brk和brk初始位置是bss段的尾部加一個隨機的偏移。2.6.26內核開始支持。

1.5 VDSO隨機化: VDSO(Virtual Dynamically-linked Shared Object,虛擬動態共享庫)將內核態的呼叫映射到用戶態的地址空間中,使得呼叫開銷更小,路徑更好。拿x86下的系統呼叫舉例,傳統的int 0x80有點慢,Intel和AMD分別實現了sysenter/sysexit和syscall/sysret,即所謂的快速系統呼叫指令,使用它們更快,但是也帶來了兼容性的問題。於是linux實現了vsyscall,程式統一呼叫vsyscall,具體的選擇由內核來決定,vsyscall的實現就在VDSO中。執行ldd /bin/sh,會發現有個linux-vdso.so.1的動態檔案,而系統中卻找不到它,它就是VDSO。linux內核從2.6.18(x86/PPC)和2.6.22(x86_64)開始支持VDSO的隨機化。

1.6 linux中ASLR的等級

在linux系統中ASLR被分為0,1,2三個等級,可以通過sudo bash -c “echo 2 > /proc/sys/kernel/randomize_va_space”設置。

0:沒有隨機化。即關閉ASLR。

1:保留的隨機化。共享庫、棧、mmap()分配的記憶體空間以及VDSO將被隨機化。

2:完全的隨機化。在1的基礎上,通過 brk()分配的記憶體空間也將被隨機化。

2.NX

NX(Non-Executable Memory,不可執行記憶體)類似於windows中的DEP(Data Execution Prevention,資料執行保護)。windows系統從xp sp2開始啟用DEP。使用gcc在彙編時–noexecstack或在鏈接時-z noexecstack或者使用execstack修改ELF檔案中PT_GNU_STACK中的p_flags可以設置程式是否需要具有可執行權限的堆棧。cat /proc/cpuinfo在flags中如果有NX表示CPU支持NX。

一些BIOS廠商可能預設會禁止這個功能,不過從Ubuntu 11.04開始內核就會忽略BIOS中關於NX的設置。下麵這張圖是在Ubuntu中NX的啟用情況。

 

二.編譯器安全防護

1.Built as PIE

前面說了EXEC的隨機化,實際上更準確的說法是PIE(Position Independent Executables,位置無關可執行檔案)。PIE只有在系統開啟ASLR和編譯時開啟-fpie -pie選項這兩個條件同時滿足時才會生效。最初因為在像x86這樣通用暫存器較少的架構上PIE的性能損失比較明顯,所以並不是所有的程式都啟用了PIE。從Ubuntu 17.10和Fedora 23開始為所有的架構都啟用了PIE。

2.Built with RELRO

RELRO(RELocation Read-Only,只讀重定位)讓加載器將重定位表中加載時解析的符號標記為只讀,這減少了GOT覆寫攻擊的面積。RELRO可以分為Partial RELRO(部分RELRO)和Full RELRO(完整RELRO)。開啟Partial RELRO的話GOT表是可寫的;開啟FULL RELRO的話GOT表是只讀的。從Fedora 23開始所有軟體包都已啟用了Full RELRO。開啟-Wl,-z,relro選項即可開啟Partial RELRO;開啟-Wl,-z,relro,-z,now選項即可開啟Full RELRO。

3.Stack Protector

Stack Protector又名canary,stack cookie……等等,類似於VS編譯器中的GS。gcc4.2中添加了-fstack-protector和-fstack-protector-all編譯引數以支持該功能,gcc4.9中添加了-fstack-protector-strong編譯引數讓保護的範圍更廣。

三.內核安全防護

1.某些發行版中特有的

(1).dmesg restrictions

在dmesg里可以查看到開機信息。若研究內核代碼,在代碼中插入printk函式,然後通過dmesg觀察是一個很好的方法。從Ubuntu 12.04 LTS開始,可以將/proc/sys/kernel/dmesg_restrict設置為1將dmesg輸出的信息當做敏感信息(預設為0)。

(2).Kernel Address Display Restriction

在linux內核漏洞利用中常常使用commit_creds和prepare_kernel_cred來完成提權,它們的地址可以從/proc/kallsyms中讀取。從Ubuntu 11.04和RHEL 7開始,/proc/sys/kernel/kptr_restrict被預設設置為1以阻止通過這種方式泄露內核地址。

2.所有發行版中都有的

(1).KPTI

今年年初的CPU漏洞讓KPTI(Kernel PageTable Isolation,內核頁表隔離)進入了人們的視野。行程地址空間被分成了內核地址空間和用戶地址空間,其中內核地址空間映射到了整個物理地址空間,而用戶地址空間只能映射到指定的物理地址空間。內核地址空間和用戶地址空間共用一個頁全域性目錄表。為了徹底防止用戶程式獲取內核資料,可以令內核地址空間和用戶地址空間使用兩組頁表集。linux內核從4.15開始支持KPTI,windows上把這個叫KVA Shadow,原理類似。更多細節請見參考資料。

(2).KASLR

KASLR中的K指kernel,也就是內核地址空間佈局隨機化。

下麵這張圖就是幾大主流操作系統(windows/linux/ios/os x/android)中ASLR和KASLR的啟用情況。不過值得註意的是Android 8.0中為4.4及以後的內核引入了KASLR。從Ubuntu 14.10開始就支持KASLR了,但並不是預設啟用的,需要在內核命令列中加入kaslr開啟。

(3).SMAP/SMEP

SMAP(Supervisor Mode Access Prevention,管理樣式訪問保護)和SMEP(Supervisor Mode Execution Prevention,管理樣式執行保護)的作用分別是禁止內核訪問用戶空間的資料和禁止內核執行用戶空間的代碼。arm裡面叫PXN(Privilege Execute Never)和PAN(Privileged Access Never)。SMEP類似於前面說的NX,不過一個是在內核態中,一個是在用戶態中。和NX一樣SMAP/SMEP需要處理器支持,可以通過cat /proc/cpuinfo查看,在內核命令列中添加nosmap和nosmep禁用。windows系統從win8開始啟用SMEP,windows內核列舉哪些處理器的特性可用,當它看到處理器支持SMEP時通過在CR4暫存器中設置適當的位來表示應該強制執行SMEP,可以通過ROP或者jmp到一個RWX的內核地址繞過。linux內核從3.0開始支持SMEP,3.7開始支持SMAP。

在沒有SMAP/SMEP的情況下把內核指標重定向到用戶空間的漏洞利用方式被稱為ret2usr。physmap是內核管理的一塊非常大的連續的虛擬記憶體空間,為了提高效率,該空間地址和RAM地址直接映射。RAM相對physmap要小得多,導致了任何一個RAM地址都可以在physmap中找到其對應的虛擬記憶體地址。另一方面,我們知道用戶空間的虛擬記憶體也會映射到RAM。這就存在兩個虛擬記憶體地址(一個在physmap地址,一個在用戶空間地址)映射到同一個RAM地址的情況。也就是說,我們在用戶空間里創建的資料,代碼很有可能映射到physmap空間。基於這個理論在用戶空間用mmap()把提權代碼映射到記憶體,然後再在physmap里找到其對應的副本,修改EIP跳到副本執行就可以了。因為physmap本身就是在內核空間里,所以SMAP/SMEP都不會發揮作用。這種漏洞利用方式叫ret2dir。

(4).Stack Protector

當然在內核中也是有這種防護的,編譯內核時設置CONFIG_CC_STACKPROTECTOR選項即可,該補丁是Tejun Heo在09年給主線kernel提交的。

2.6.24:首次出現該編譯選項並實現了x64平臺的行程背景關係棧保護支持

2.6.30:新增對內核中斷背景關係的棧保護和對x32平臺行程背景關係棧保護支持

3.14:對該功能進行了一次升級以支持gcc的-fstack-protector-strong引數,提供更大範圍的棧保護

關於函式傳回地址的問題屬於CFI(Control Flow Integrity,控制流完整性保護)中的後向控制流完整性保護。近幾年人們提出了safe-stack和shadow-call-stack引入一個專門儲存傳回地址的棧替代Stack Protector。可以從下圖看到shadow-call-stack開銷更小一點。這項技術已經應用於android,而linux內核仍然在等待硬體的支持。

(5). address protection

由於內核空間和用戶空間共享虛擬記憶體地址,因此需要防止用戶空間mmap的記憶體從0開始,從而緩解NULL解取用攻擊。windows系統從win8開始禁止在零頁分配記憶體。從linux內核2.6.22開始可以使用sysctl設置mmap_min_addr來實現這一保護。從Ubuntu  9.04開始,mmap_min_addr設置被內置到內核中(x86為64k,ARM為32k)。

參考資料

想了想還缺glibc一些東西,但是這個資料比較多,篇幅也較長,所以就不寫了。一些稍微冷門一點的由於不太熟悉,也沒寫了。

1.Fedora Security Features

(https://fedoraproject.org/wiki/Security_Features_Matrix)

2.Ubuntu Security Features

(https://wiki.ubuntu.com/Security/Features)

3.Debian Security Features

(https://wiki.debian.org/Security/Features)

4.linux kernel defence map

(https://github.com/a13xp0p0v/linux-kernel-defence-map/)

5.Address space layout randomization

(https://en.wikipedia.org/wiki/Address_space_layout_randomization)

6.Vulnerability and threat mitigation features in Red Hat Enterprise Linux

(https://access.redhat.com/articles/65299)

7.Breaking Kernel Address Space Layout Randomization with Intel TSX

(https://www.blackhat.com/docs/us-16/materials/us-16-Jang-Breaking-Kernel-Address-Space-Layout-Randomization-KASLR-With-Intel-TSX.pdf)

8.CPU漏洞分析彙總貼

(https://bbs.pediy.com/thread-225728.htm)

9.原創技術乾貨|解讀Linux安全機制之棧上限溢位保護

(http://mini.eastday.com/mobile/160128193251250.html)

10.Making C Less Dangerous

(https://outflux.net/slides/2018/lss/danger.pdf)

 

原文轉自: 看雪論壇houjinyi

https://bbs.pediy.com/thread-226696.htm

    閱讀原文

    赞(0)

    分享創造快樂