防止fork暴力攻擊,Linux新增Brute安全模塊
Linux的很多嚴重的漏洞,尤其是提權漏洞都使用了暴力fork()系統調用導致內核崩潰,從而突破內存限制而成功的,例如 Stack Clash 漏洞,“心臟出血”漏洞以及新爆出的sudo CVE-2021-3156等。為了一勞永逸的解決此類漏洞,Linux安全模塊(LSM)新增加了一個“Brute”模塊,以檢測和阻止這類攻擊。
最近Brute補丁程序集的發布了第6版版本,預計很快就可以發布到主線分支中去。
“Brute”補丁集于去年9月John Wood發布為RFC,最初名稱為“fbfam”( fork brute force attack mitigation,fork暴力攻擊緩解),后在社區商量下改名了并將其變成LSM。
關于這類問題的解決實際上由來已久了。grsecurity的內核補丁早就有 GRKERNSEC_BRUTE功能用以減少使用蠻力攻擊 fork(), 以及預防setuid/ setgid的二進制文件的攻擊。Weinberger在2014中發布的補丁中也使用的類似的技術,以延緩fork(),由于fork()崩潰導致的問題(這可能意味著它是一個攻擊的一部分)。 但是這些嘗試并沒有進一步的推動。
在Brute補丁的文檔中 ,Wood描述了Brute LSM所針對的行為類型?;舅枷胧?,有幾種類型的攻擊可以使用多次fork()來接收所需的內存布局。 每個fork的子進程都可以通過各種方式進行探測,如果這些探測失敗并導致子進程崩潰,則可以簡單地重新fork另一個子進程再試一次。因為使用創建的子進程與其父進程共享相同的內存布局,所以成功的探針可以提供可用來突破Linux虛擬內存地址空間隨機化布局(ASLR),可以用來探測堆棧Stack_canaries或其他有敏感信息。
Brute采用不同于grsecurity或Weinberger修補程序的方法,因為它不會簡單地延遲隨后的fork()在檢測到問題時調用。取而代之的是,Brute殺死了與攻擊相關的所有進程。 此外,Brute 檢測更多類型的fork()使用攻擊(包括探測父進程而不是子進程的攻擊。 它還著重于為了避免誤報而越過特權邊界的進程崩潰。
Brute通過統計崩潰率來實現。Brute收集有關已在一組已經fork進程中發生的“失敗”數量的信息,但是在其中沒有使用執行任何新操作execve()。一個brute_stats 所有這些進程之間共享結構。執行一個新程序會導致一個新的結構來跟蹤新的(潛在的)結構中的故障fork()層次。
從進程啟動到進程或其任何共享內存布局的子進程(即沒有 execve())崩潰或連續崩潰之間的時間間隔,最終用來確定是否發生攻擊的時間。為了防止多次調用,插件使用EMA(指數移動平均值)計數,一旦發生五次崩潰,就會計算該時期 (EMA)。 EMA用于確定是否正在發生“快速暴力”攻擊。 如果兩次崩潰之間的時間間隔的EMA下降到30秒的閾值以下,就會觸發緩解攻擊。對于“慢速暴力”變體,將層次結構中的絕對崩潰次數與200個閾值進行比較。
使用ask_fatal_signal() LSM鉤子,添加作為集合中的第一個補丁。 每當內核向進程傳遞致命信號時,就會調用該方法。 Brute還使用現有的 task_alloc() 鉤子來檢測 fork()調用,使用 bprm_committing_creds() 鉤子來檢測 execve()調用,以及使用 task_free() 鉤子來清理所有內容。
通過跟蹤對執行新程序時發生的各種用戶和組ID的更改,可以實現安全邊界檢查。 沒有提到 Linux功能 補丁中 ,但是功能更改也將表明特權邊界已被突破; 也許這會在以后增加。除ID更改之外,還可以使用檢測到網絡的使用 socket_sock_rcv_skb()LSM鉤子。通過執行setuid/setgid程序或通過網絡接收數據來將崩潰檢查限制為跨越特權邊界的那些進程,這樣可以減少誤報的數量。