當前位置:
首頁 > 新聞 > Linux內存管理中緩存失效漏洞分析及利用

Linux內存管理中緩存失效漏洞分析及利用

概述

自內核版本3.16以來,Linux內存管理中存在一個緩存失效漏洞(CVE-2018-17182),本文是對該漏洞的分析。儘管這一漏洞所在的代碼可以被比較強大的沙盒上下文所訪問,但在本文中我們介紹了一種在未配置增強安全性的Linux內核環境中利用漏洞的方式(特別是內核為linux-image-4.15.0-34-generic,版本在4.15.0-4.34.37之間的Ubuntu 18.04操作系統)。在文章中,還展現了對內核的配置是如何影響內核漏洞利用難度的。

錯誤報告和漏洞利用方法已經提交,編號為Issue 1664( https://bugs.chromium.org/p/project-zero/issues/detail?id=1664 )。

該漏洞已經在4.18.9、4.14.71、4.9.128、4.4.157和3.16.58版本中實現修復。

漏洞詳情

當用戶空間發生頁錯誤時(例如必須根據需要進行分頁),Linux內核需要查找包含錯誤地址的虛擬內存區域(VMA,vm_area_struct),以確定如何處理故障。查找VMA的慢速路徑(Slowpath)必須要經歷VMA的紅黑樹。為了進一步提高性能,Linux還有一個快速路徑(Fastpath),如果這個VMA最近被使用過,那麼就可以不再經過紅黑樹。

隨著時間的推移,快速路徑的實現方法發生了變化。從3.15版本( https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=615d6e8756c87149f2d4c1b93d471bca002bd849 )開始,Linux使用具有4個Slot的逐線程VMA緩存,在mm/vmacache.c和include/linux/vmacache.h中實現。每當通過慢速路徑成功找到時,vmacache_update()會在數組current->vmacache.vmas的條目中存儲指向VMA的指針,從而允許下一次查找時能使用快速路徑。

需要注意的是,VMA緩存是逐線程進行的,但VMA會與整個進程相關聯。更準確的說,是使用mm_struct結構,從現在開始,這一點將在我們的分析中被忽略,因為它與漏洞無關。因此,當VMA被釋放時,必須清空所有線程的VMA高速緩存,否則下一次VMA查找將會找到一個懸垂指針(Dangling Pointer)。但是,由於進程中可以包含許多線程,所以需要遍歷所有線程的VMA緩存會出現性能問題。

為了解決這個問題,mm_struct結構和每個線程的vmacache結構都標有序列號。當VMA在vmacache_valid()中進行快速路徑查找時,如果它發現current->vmacache.seqnum與current->mm->vmacache_seqnum不匹配,它就會擦除當前線程的VMA緩存的內容,並更新其序列號。

mm_struct和VMA緩存的序列號只有32位長度,這意味著它們可能會有溢出的風險。為了確保當current->mm->vmacache_seqnum實際增加232次時VMA緩存不會認為其有效,vmacache_invalidate()(負責遞增current->mm->vmacache_seqnum的函數)中存在一個特殊情況:當current->mm->vmacache_seqnum重新回到0時,它會調用vmacache_flush_all()來擦除與current->mm關聯的所有VMA緩存的內容。執行vmacache_flush_all()所消耗的性能非常高,它會遍歷主機上的所有線程,檢查與mm_struct結構是否相關聯,然後在必要時刷新線程的VMA緩存。

在3.16版本中,對其進行了一次優化( https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=6b4ebc3a9078c5b7b8c4cf495a0b1d2d0e0bfe7a ):如果mm_struct結構僅與單個線程相關聯,那麼vmacache_flush_all()將不會執行任何操作,具體取決於每個VMA高速緩存失效之前是否進行了VMA查找。因此,在單線程進程中,VMA緩存的序列號始終近似於mm_struct的序列號:

/*

* Single threaded tasks need not iterate the entire

* list of process. We can avoid the flushing as well

* since the mm"s seqnum was increased and don"t have

* to worry about other threads" seqnum. Current"s

* flush will occur upon the next lookup.

*/

if (atomic_read(&mm->mm_users) == 1)

return;

然而,這種優化方式是不正確的,因為它沒有考慮如果先前的單線程進程在mm_struct的序列號已經回到0之後立即創建新線程的這種情況。在這種情況下,第一個線程的VMA緩存的序列號仍然是0xffffffff,第二個線程可以再次使得mm_struct的序列號變為0xffffffff。此時,第一個線程的VMA緩存(其中包含著懸垂指針)將再次被視為有效,從而允許在第一個線程的VMA緩存中使用釋放的VMA指針。

針對這一漏洞,修復方式( https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/mm/vmacache.c?id=7a9cdebdcc17e426fb5287e4a82db1dfe86339b2 )是將序列號更改為64位,從而使溢出無法發生,同時刪去原有的溢出處理邏輯。

漏洞影響

從根本上來說,如果一個進程能夠運行足夠長的時間,並能夠進行一些指定的系統調用,那麼它就可以使引用計數器溢出,使用mmap()/munmap()管理內存映射,再使用clone()創建一個線程,從而實現漏洞利用。在MAP_FIXED可用的情況下,讓引用計數器溢出大約需要一個小時的時間。這些系統調用不需要任何許可權,即使是在seccomp-sandboxed的上下文中也經常允許使用它們,例如Chrome Renderer Sandbox(mmap、munmap、clone)、gVisor沙箱組件以及Docker的seccomp策略。

為了簡單起見,我的漏洞利用方法中使用了多種其他的內核介面,因此實際上不僅僅在這些沙箱的內部工作。特別是,它使用/dev/kmsg讀取dmesg日誌,並使用eBPF數組影響內核中由用戶控制的頁分配器以及可變單頁分配器(Mutable Single-page Allocation)。如果攻擊者願意花費更長的時間,他們可能會避免使用這些介面。

有趣的是,如果內核允許普通用戶訪問dmesg,Docker的默認配置也不會阻止對dmesg日誌的訪問。儘管/dev/kmsg並不存在,但由於某種原因,seccomp策略將syslog()系統調用列入了白名單。

對BUG_ON()、WARN_ON_ONCE()和dmesg的分析

第一次UAF(Use-After-Free)發生的函數是vmacache_find()。在首次添加此函數後,在漏洞產生前,它按照以下方式訪問VMA緩存:

for (i = 0; i

struct vm_area_struct *vma = current->vmacache[i];

if (vma && vma->vm_start vm_end > addr) {

BUG_ON(vma->vm_mm != mm);

return vma;

}

}

當這段代碼遇到緩存的VMA,其邊界包含提供的地址addr時,它會檢查VMA的->vm_mm指針是否與預期的mm_struct相匹配。除非發生了內存安全問題,否則二者始終應該匹配。如果發現不匹配,那麼將會使用BUG_ON()終止這一過程。BUG_ON()用於處理內核線程檢測到嚴重問題的情況,這些問題往往無法在上下文中得到有效的解決。在默認的內核配置中,BUG_ON()通常會將帶有寄存器轉儲的回溯內容列印到dmesg日誌緩衝區,然後強制終止當前線程。這樣一來,有時會影響系統其他部分的正常工作。舉例來說,如果崩潰的代碼帶有一個重要的鎖,那麼其他任何試圖獲取該鎖的線程都會被死鎖,但這一過程中能夠成功保持其他的系統處於可用的狀態。只有當內核監測到崩潰發生在關鍵環境中(例如中斷處理程序)時,才會導致整個系統崩潰。

相同的處理程序代碼用於處理內核代碼中的意外崩潰,例如頁錯誤和非白名單地址的一般保護錯誤。默認情況下,如果可能,內核只會嘗試終止有問題的線程。

內核崩潰的處理過程其實是可用性、可靠性和安全性這三方面之間的權衡。系統所有者可能會希望系統能儘可能長時間的運行,即使是系統的某些部分崩潰,也比發生內核崩潰(Kernel Panic)造成重要服務的數據丟失或停止服務要好。同樣,系統所有者可能更希望在沒有外部調試器的情況下實時調試系統上的內核錯誤,因為如果在觸發錯誤後整個系統終止了,那麼可能會更難以有效調試。

另一方面,如果是攻擊者想要利用內核漏洞實現攻擊,可能會更想要能在不觸發系統重啟的前提下實現多次攻擊的能力,並且希望能夠讀取第一次嘗試過程中產生的崩潰日誌,並使用該信息來進行更複雜的第二次攻擊。

內核提供了兩個可用於調整此類行為的sysctl,具體要取決於系統所有者所做的權衡:

1、kernel.panic_on_oops將會在BUG_ON()被觸發或內核崩潰時,自動導致內核崩潰。可以通過配置變數CONFIG_PANIC_ON_OOPS來配置其初始值。在默認情況下,它在內核中是關閉的,在發布版本中啟用它可能是一個壞主意,但在Android中默認啟用。

2、kernel.dmesg_restrict控制非root用戶是否可以訪問dmesg日誌,其中包括內核崩潰的寄存器轉儲內容和堆棧跟蹤內容,可以使用配置變數CONFIG_SECURITY_DMESG_RESTRICT對其初始值進行配置。在默認情況下,它在內核中是關閉的,但在Debian中默認啟用,Android是依靠SELinux來阻止訪問dmesg。

舉例來說,Ubuntu無法實現這些功能。

上面的代碼片段,在提交後的同一個月內,進行了修改:

for (i = 0; i

struct vm_area_struct *vma = current->vmacache[i];

- if (vma && vma->vm_start vm_end > addr) {

- BUG_ON(vma->vm_mm != mm);

+ if (!vma)

+ continue;

+ if (WARN_ON_ONCE(vma->vm_mm != mm))

+ break;

+ if (vma->vm_start vm_end > addr)

return vma;

- }

}

目前,Ubuntu等發行版本中使用的都是修改後的代碼。

這裡的第一個變化,就是將懸垂指針的完整性檢查放在了地址比較之前。第二個變化更加有趣,是將BUG_ON()換為了WARN_ON_ONCE()。

WARN_ON_ONCE()會將調試信息輸出到dmesg,類似於BUG_ON()列印的內容。與BUG_ON()的區別在於,WARN_ON_ONCE()僅會在第一次觸發時列印調試信息,並且繼續執行。現在,當內核在VMA緩存快速路徑查找過程中檢測到懸垂指針時,也就是當它檢測到一次UAE時,它只會從快速路徑中退出,並回到紅黑樹的查找,而這一功能還可以正常進行。

這樣也符合內核的策略,默認情況下儘可能保證系統的運行。如果由於某種原因,在這裡發生了Use-After-Free漏洞,內核可能會啟發式的減輕漏洞的影響,並保持該進程正常工作。

但是,在內核發現發生內存損壞後,僅僅列印警告的策略也是存在問題的。正常來講,當內核注意到內存損壞等安全事件後,理論上應該發生內核崩潰(Kernel Panic)。簡單的觸發一個WARN()並不是一個好選擇,因為WARN()同樣也適用於與內核安全性無關的各種事件。因此,在安全相關的地方,WARN_ON()的一些用法已經替換為CHECK_DATA_CORRUPTION(),它允許在內核配置時切換BUG()與WARN()的行為。但是,CHECK_DATA_CORRUPTION()又僅僅適用於鏈表操作代碼和addr_limit_user_check()。在VMA緩存中進行的檢查,仍然使用經典的WARN_ON_ONCE()。

考慮到這一點,針對這個函數,進行了第三次重要的調整。然而,這次調整才剛剛進行,並且將在尚未發布的4.19內核中發布。因此,這部分修改的內容不會影響我們在當前環境中的攻擊嘗試。

for (i = 0; i

- struct vm_area_struct *vma = current->vmacache.vmas[i];

+ struct vm_area_struct *vma = current->vmacache.vmas[idx];

- if (!vma)

- continue;

- if (WARN_ON_ONCE(vma->vm_mm != mm))

- break;

- if (vma->vm_start vm_end > addr) {

- count_vm_vmacache_event(VMACACHE_FIND_HITS);

- return vma;

+ if (vma) {

+#ifdef CONFIG_DEBUG_VM_VMACACHE

+ if (WARN_ON_ONCE(vma->vm_mm != mm))

+ break;

+#endif

+ if (vma->vm_start vm_end > addr) {

+ count_vm_vmacache_event(VMACACHE_FIND_HITS);

+ return vma;

+ }

}

+ if (++idx == VMACACHE_SIZE)

+ idx = 0;

}

在經過這一修改之後,除非使用調試選項CONFIG_DEBUG_VM_VMACACHE構建內核,否則將會完全跳過完整性檢查。

漏洞利用:增加序列號

要利用該漏洞,必須將序列號增加約233次。因此,用於遞增序列號的原語必須要確保效率,這樣才能提升漏洞利用的整體效率。

每個系統調用可以產生兩個序列號增量,方法如下:創建一個跨越3個頁的匿名VMA,然後重複使用帶有MAP_FIXED的mmap()將中間頁替換為等效的VMA。這樣一來,會導致mmap()首先將VMA拆分成3個VMA,然後替換掉中間的VMA,然後再將3個VMA合併到一起,從而導致在合併VMA時刪除掉的兩個VMA所對應的緩存失效。

漏洞利用:替換VMA

如果我們希望在不釋放Slab Backing Page的情況下,進行Use-After-Free攻擊,那麼需要將目標放在分配器/頁分配器上:

1、獲取在同一進程中重用的vm_area_struct,該進程將能夠使用這一VMA,但是該進程的VMA緩存將被允許包含指向VMA的指針。

2、釋放vm_area_struct,使其位於Slab分配器的Freelist上,然後嘗試訪問它。但是,Ubuntu使用的SLUB分配器至少會用內核地址替換vm_area_struct的前8個位元組,這使得VMA緩存查找功能無法返回這一內容,因為條件vma->vm_start vm_end > addr不能成立。

3、釋放vm_area_struct,使其位於Slab分配的Freelist上,然後在另一個進程中分配它。這將導致命中WARN_ON_ONCE(),因此VMA緩存查找功能不會返回VMA。

4、釋放vm_area_struct,使其位於Slab分配的Freelist上,然後從已經和vm_area_struct合併的Slab進行分配。這需要存在一個混合的Slab,而在Ubuntu 18.04上,似乎是不存在的。

因此,要利用此漏洞,就必須將Backing Page釋放回頁分配器,然後通過某種方式重新對頁面進行分配,以允許在其中放置受控制的數據。我們可以使用各種內核介面,例如:

(1)Pipe Page

優點:不會擦除分配的內容,如果splice()可用,就允許使用任意頁內偏移量進行寫入操作,並且支持頁對齊(Page-Aligned)。

缺點:如果沒有首先釋放頁面,就無法進行多次寫入和重新分配。

(2)BPF地圖

優先:可以反覆讀取和寫入用戶空間的內容、支持頁對齊。

缺點:會擦除分配的內容。

我們在實際的漏洞利用中,選擇的是第二種方法。

漏洞利用:從dmesg泄漏指針

我們在漏洞利用過程中,希望獲得以下信息:

mm_struct的地址

Use-After-Free的VMA地址

載入內核代碼的地址

至少在Ubuntu 18.04內核中,前兩個在WARN_ON_ONCE()出發的寄存器轉儲內容中可以直接看到,因此可以很容易地從dmesg中提取。mm_struct的地址在RDI中,VMA的地址在RAX中。但是,指令指針是無法直接找到的,因為RIP和棧經過了符號化,通用寄存器中也都不包含指令指針。

在內核回溯中,可以包含多組寄存器:當棧回溯邏輯遇到中斷幀時,會生成另一個寄存器轉儲。由於我們可以通過用戶空間地址上的頁錯誤觸發WARN_ON_ONCE(),並且用戶空間地址上的頁錯誤可能發生在syscall上下文中任何用戶控制項訪問中(通過copy_from_user()/copy_to_user()/...),我們可以從中選擇一個包含相關信息的調用節點。事實證明,如果寫入eventfd將會觸發usercopy,此時R8仍然包含指向eventfd_fops結構的指針。

當漏洞利用開始時,它將VMA替換為零內存,然後針對損壞的VMA緩存觸發VMA查找過程,故意觸發WARN_ON_ONCE()。這會生成一個警告,如下所示:

[ 3482.271265] WARNING: CPU: 0 PID: 1871 at /build/linux-SlLHxe/linux-4.15.0/mm/vmacache.c:102 vmacache_find+0x9c/0xb0

[...]

[ 3482.271298] RIP: 0010:vmacache_find+0x9c/0xb0

[ 3482.271299] RSP: 0018:ffff9e0bc2263c60 EFLAGS: 00010203

[ 3482.271300] RAX: ffff8c7caf1d61a0 RBX: 00007fffffffd000 RCX: 0000000000000002

[ 3482.271301] RDX: 0000000000000002 RSI: 00007fffffffd000 RDI: ffff8c7c214c7380

[ 3482.271301] RBP: ffff9e0bc2263c60 R08: 0000000000000000 R09: 0000000000000000

[ 3482.271302] R10: 0000000000000000 R11: 0000000000000000 R12: ffff8c7c214c7380

[ 3482.271303] R13: ffff9e0bc2263d58 R14: ffff8c7c214c7380 R15: 0000000000000014

[ 3482.271304] FS: 00007f58c7bf6a80(0000) GS:ffff8c7cbfc00000(0000) knlGS:0000000000000000

[ 3482.271305] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033

[ 3482.271305] CR2: 00007fffffffd000 CR3: 00000000a143c004 CR4: 00000000003606f0

[ 3482.271308] DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000

[ 3482.271309] DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400

[ 3482.271309] Call Trace:

[ 3482.271314] find_vma+0x1b/0x70

[ 3482.271318] __do_page_fault+0x174/0x4d0

[ 3482.271320] do_page_fault+0x2e/0xe0

[ 3482.271323] do_async_page_fault+0x51/0x80

[ 3482.271326] async_page_fault+0x25/0x50

[ 3482.271329] RIP: 0010:copy_user_generic_unrolled+0x86/0xc0

[ 3482.271330] RSP: 0018:ffff9e0bc2263e08 EFLAGS: 00050202

[ 3482.271330] RAX: 00007fffffffd008 RBX: 0000000000000008 RCX: 0000000000000001

[ 3482.271331] RDX: 0000000000000000 RSI: 00007fffffffd000 RDI: ffff9e0bc2263e30

[ 3482.271332] RBP: ffff9e0bc2263e20 R08: ffffffffa7243680 R09: 0000000000000002

[ 3482.271333] R10: ffff8c7bb4497738 R11: 0000000000000000 R12: ffff9e0bc2263e30

[ 3482.271333] R13: ffff8c7bb4497700 R14: ffff8c7cb7a72d80 R15: ffff8c7bb4497700

[ 3482.271337] ? _copy_from_user+0x3e/0x60

[ 3482.271340] eventfd_write+0x74/0x270

[ 3482.271343] ? common_file_perm+0x58/0x160

[ 3482.271345] ? wake_up_q+0x80/0x80

[ 3482.271347] __vfs_write+0x1b/0x40

[ 3482.271348] vfs_write+0xb1/0x1a0

[ 3482.271349] SyS_write+0x55/0xc0

[ 3482.271353] do_syscall_64+0x73/0x130

[ 3482.271355] entry_SYSCALL_64_after_hwframe+0x3d/0xa2

[ 3482.271356] RIP: 0033:0x55a2e8ed76a6

[ 3482.271357] RSP: 002b:00007ffe71367ec8 EFLAGS: 00000202 ORIG_RAX: 0000000000000001

[ 3482.271358] RAX: ffffffffffffffda RBX: 0000000000000000 RCX: 000055a2e8ed76a6

[ 3482.271358] RDX: 0000000000000008 RSI: 00007fffffffd000 RDI: 0000000000000003

[ 3482.271359] RBP: 0000000000000001 R08: 0000000000000000 R09: 0000000000000000

[ 3482.271359] R10: 0000000000000000 R11: 0000000000000202 R12: 00007ffe71367ec8

[ 3482.271360] R13: 00007fffffffd000 R14: 0000000000000009 R15: 0000000000000000

[ 3482.271361] Code: 00 48 8b 84 c8 10 08 00 00 48 85 c0 74 11 48 39 78 40 75 17 48 39 30 77 06 48 39 70 08 77 8d 83 c2 01 83 fa 04 75 ce 31 c0 5d c3 0b 31 c0 5d c3 90 90 90 90 90 90 90 90 90 90 90 90 90 90 0f

[ 3482.271381] ---[ end trace bf256b6e27ee4552 ]---

此時,可以創建一個虛假的VMA,其中包含正確的mm_struct指針(從RDI的位置泄漏)。它通過引用偽數據結構來填充其他欄位(通過使用RAX泄漏的WMA指針,創建指向偽VMA的指針)以及指向內核代碼的指針(通過使用頁錯誤異常幀泄漏的R8來繞過KASLR)。

漏洞利用:JOP

其實,有一些非常優雅的漏洞利用方式,比如將偽造的可寫VMA覆蓋在已經存在的只讀頁上,或者類似這樣的操作。但是,這裡的漏洞利用方式只使用經典的跳轉方法。

為了觸發第二次Use-After-Free,我們對沒有頁表項的地址執行了寫入內存訪問。此時,內核的頁錯誤處理程序通過page_fault -> do_page_fault -> __do_page_fault -> handle_mm_fault -> __handle_mm_fault -> handle_pte_fault -> do_fault -> do_shared_fault -> __do_fault進入,此時它會執行間接調用:

static int __do_fault(struct vm_fault *vmf)

{

struct vm_area_struct *vma = vmf->vma;

int ret;

ret = vma->vm_ops->fault(vmf);

其中,vma是我們控制的VMA結構,因此我們可以獲得對指令指針的控制。R13中包含指向vma的指針。我們使用的JOP鏈如下,它非常簡陋(在完成工作之後就會崩潰),但確實有效。

首先,將VMA指針移動到RDI:

ffffffff810b5c21: 49 8b 45 70 mov rax,QWORD PTR [r13+0x70]

ffffffff810b5c25: 48 8b 80 88 00 00 00 mov rax,QWORD PTR [rax+0x88]

ffffffff810b5c2c: 48 85 c0 test rax,rax

ffffffff810b5c2f: 74 08 je ffffffff810b5c39

ffffffff810b5c31: 4c 89 ef mov rdi,r13

ffffffff810b5c34: e8 c7 d3 b4 00 call ffffffff81c03000

然後,要完全控制RDI:

ffffffff810a4aaa: 48 89 fb mov rbx,rdi

ffffffff810a4aad: 48 8b 43 20 mov rax,QWORD PTR [rbx+0x20]

ffffffff810a4ab1: 48 8b 7f 28 mov rdi,QWORD PTR [rdi+0x28]

ffffffff810a4ab5: e8 46 e5 b5 00 call ffffffff81c03000

此時,我們可以調用run_cmd(),它使用空格分隔的路徑和參數列表作為唯一參數,生成root許可權的用戶模式幫助程序。這使我們能夠以root許可權運行二進位文件。(感謝Mark指出,如果已經控制了RDI和RIP,那麼就不用進行在CR4中翻轉SM*P位這樣瘋狂的操作,只需要生成一個Usermode Helper)。

啟動Usermode Helper後,內核由於頁錯誤而發生崩潰,因為JOP鏈沒有正常終止。但是,由於這隻會終止導致錯誤發生的進程,因此並不重要。

修復時間表

這個漏洞在2018年9月12日被報告。兩天後,在上游的內核樹中就完成了這一漏洞的修復。與其他廠商相比,這樣的修復速度非常快。下游的廠商理論上可以使用修復後的版本或及時安裝補丁。

然而,上游的內核中實現修復並不意味著用戶系統中的漏洞也已經被修復。這些修復程序的發布流程大致如下:

1、在上游內核中實現修復;

2、該補丁被反向一直到上游支持的穩定內核中;

3、發行版本操作系統將來自上游的穩定內核中的更改,合併到其內核中;

4、用戶安裝新的發行版本內核。

請注意,由於在進行步驟1之後,這一補丁就轉為公開,可能攻擊者會藉助公開的內容進行漏洞利用,但用戶只有在完成全部4個步驟之後,其操作系統才能受到保護。

上游支持的穩定內核4.18、4.14、4.9和4.4的補丁於2018年9月19日發布,在補丁程序發布後的5天,發行版本陸續加入了這一補丁。

上游穩定版本的內核更新非常頻繁,以4.14版本為例,下面是最新的長期維護版本:

4.14.72(2018-09-26)

4.14.71(2018-09-19)

4.14.70(2018-09-15)

4.14.69(2018-09-09)

4.14.68(2018-09-05)

4.14.67(2018-08-24)

4.14.66(2018-08-22)

4.9和4.4長期維護內核版本的更新頻率非常相似,只有3.16長期維護內核在2018年9月15日(3.16.58)和2018年6月16日(3.16.57)之間沒有任何更新。

但是,Linux發行版通常不會頻繁的發布內核更新。例如,Debian穩定版基於4.9版本的內核,但截止到9月26日,其內核的最後更新日期仍然為8與21日。同樣,Ubuntu 16.04版本的內核最後更新日期為8月27日。Android每月只會發布一次安全更新。因此,當上游穩定內核提供關鍵安全修復程序後,用戶還需要等到幾周的時間才能獲取到修復程序,特別是在沒有公開發布漏洞影響範圍的情況下。

這一漏洞於9月18日在OSS-Security郵件列表上公布,並在9月19日分配了CVE編號,然而截至9月26日,Debian和Ubuntu(在16.04和18.04版本中)都還將這個漏洞跟蹤為未修復:

https://security-tracker.debian.org/tracker/CVE-2018-17182

https://people.canonical.com/~ubuntu-security/cve/2018/CVE-2018-17182.html

Fedora在9月22日推送了用戶更新:

https://bugzilla.redhat.com/show_bug.cgi?id=1631206#c8

結論

這一漏洞展現了內核的配置對於針對內核漏洞編寫漏洞利用程序的難度可以產生較大的影響。由此我們知道,隨意調整與安全相關的內核配置選項是一個不太穩妥的行為,因為其中的一些配置,例如kernel.dmesg_restrict sysctl,在啟用時有效平衡了可用性、可靠性與安全性。

根據修復時間表,我們發現從發布上游修復程序到用戶可使用修復程序之間,存在一個足夠大的窗口期,攻擊者可能會在此期間編寫內核漏洞的利用程序,實現對受漏洞影響主機的攻擊。


喜歡這篇文章嗎?立刻分享出去讓更多人知道吧!

本站內容充實豐富,博大精深,小編精選每日熱門資訊,隨時更新,點擊「搶先收到最新資訊」瀏覽吧!


請您繼續閱讀更多來自 嘶吼RoarTalk 的精彩文章:

開掛的惡意軟體——Part 1:簡單的CMD反向shell
如何緩解易受攻擊的Wireshark?

TAG:嘶吼RoarTalk |