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