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

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)

    分享創造快樂