攻擊全解析:從權(quán)限提升原理到防御實(shí)戰(zhàn))
1. 從“為什么”說(shuō)起提權(quán)攻擊的真實(shí)威脅面我最早接觸“提權(quán)”這個(gè)詞是在一次內(nèi)部系統(tǒng)的安全審計(jì)復(fù)盤里。當(dāng)時(shí)某臺(tái)業(yè)務(wù)服務(wù)器已經(jīng)被入侵者拿到低權(quán)限賬戶但對(duì)方并沒(méi)有止步于此——他利用系統(tǒng)里一個(gè)疏于維護(hù)的第三方組件在幾小時(shí)內(nèi)就把權(quán)限提升到了管理員級(jí)別隨后橫向移動(dòng)、批量打包數(shù)據(jù)。那次復(fù)盤給我留下一個(gè)很深的印象很多防守團(tuán)隊(duì)會(huì)把大量精力放在邊界防護(hù)上卻忽略了“一旦邊界被突破內(nèi)部權(quán)限如何被一步步放大”這條鏈路。提權(quán)全稱是權(quán)限提升Privilege Escalation本質(zhì)上就是攻擊者在已經(jīng)獲得一定權(quán)限的基礎(chǔ)上想方設(shè)法拿到更高權(quán)限的過(guò)程。你可以把它理解成一個(gè)普通員工先混進(jìn)了公司大門然后想盡辦法搞到CEO辦公室的門禁卡。這個(gè)過(guò)程的可怕之處在于它往往是整個(gè)攻擊鏈條里承上啟下的關(guān)鍵環(huán)節(jié)——前面負(fù)責(zé)“進(jìn)門”后面負(fù)責(zé)“搞事”而提權(quán)正好卡在中間決定了攻擊者能搞多大的事。從技術(shù)實(shí)現(xiàn)的角度看提權(quán)手段五花八門但歸大類的話絕大多數(shù)都能收進(jìn)兩個(gè)籃子里一類是溢出提權(quán)利用系統(tǒng)或軟件在內(nèi)存處理上的缺陷強(qiáng)行奪取控制權(quán)另一類是第三方組件提權(quán)利用某些自帶高權(quán)限或存在配置缺陷的組件服務(wù)借刀殺人拿到高權(quán)限。這篇文章就把這兩條路徹底講透包括它們的原理、現(xiàn)實(shí)中的形態(tài)、防御思路以及作為防守方你該怎么排查和封堵。適合讀這篇文章的人我覺(jué)得有三類一類是做安全運(yùn)維和系統(tǒng)加固的工程師你需要知道該把力氣花在哪兒一類是剛?cè)胄械臐B透測(cè)試人員你需要建立對(duì)提權(quán)手法的體系化認(rèn)知而不是零散地刷漏洞報(bào)告還有一類是開(kāi)發(fā)人員第三方組件提權(quán)這個(gè)方向跟你關(guān)系特別大因?yàn)槟汶S手引用的一個(gè)庫(kù)、一個(gè)服務(wù)可能就是你系統(tǒng)里權(quán)限放大的那扇暗門。在展開(kāi)具體技術(shù)之前先放一句話在這提權(quán)問(wèn)題的本質(zhì)是系統(tǒng)里“運(yùn)行時(shí)的身份邊界”沒(méi)有被嚴(yán)格守住。所有技術(shù)細(xì)節(jié)都是圍繞這句話展開(kāi)的。2. 基礎(chǔ)認(rèn)知權(quán)限模型與提權(quán)的基本分類2.1 權(quán)限模型為什么會(huì)有“提權(quán)”這回事要理解提權(quán)先要理解操作系統(tǒng)為什么要設(shè)計(jì)“權(quán)限”這個(gè)東西?,F(xiàn)代操作系統(tǒng)幾乎全都采用了“主體-客體”的訪問(wèn)控制模型主體是進(jìn)程、用戶這類主動(dòng)發(fā)起操作的實(shí)體客體是文件、注冊(cè)表、系統(tǒng)服務(wù)這類被操作的對(duì)象。在這個(gè)模型里主體能對(duì)客體做什么取決于主體持有什么樣的令牌或身份標(biāo)識(shí)。拿最普及的Windows系統(tǒng)舉例系統(tǒng)里有一張內(nèi)置的訪問(wèn)令牌Access Token它記錄了當(dāng)前用戶或進(jìn)程的用戶IDSID、所屬組、以及各項(xiàng)特權(quán)Privilege。當(dāng)你嘗試打開(kāi)一個(gè)文件或啟動(dòng)一個(gè)服務(wù)時(shí)系統(tǒng)安全參考監(jiān)視器SRM會(huì)拿你令牌里的SID和文件的安全描述符做比對(duì)判斷你是不是擁有對(duì)應(yīng)的訪問(wèn)權(quán)限。問(wèn)題在于權(quán)限本身是有級(jí)別之分的而且不同級(jí)別之間的邊界并非牢不可破。普通用戶通常運(yùn)行在“標(biāo)準(zhǔn)用戶”級(jí)別很多敏感操作被限制而管理員賬戶擁有更高的特權(quán)集可以安裝驅(qū)動(dòng)、修改系統(tǒng)配置、訪問(wèn)其他用戶的數(shù)據(jù)。攻擊者一開(kāi)始拿到的往往是前者而提權(quán)就是在“標(biāo)準(zhǔn)用戶”這個(gè)平臺(tái)上想辦法跳上“管理員”甚至“SYSTEM”級(jí)別的船。需要特別說(shuō)明的是提權(quán)在學(xué)術(shù)上還常常分成“縱向提權(quán)”和“橫向提權(quán)”??v向是從低權(quán)限到高權(quán)限橫向則是從普通用戶A到普通用戶B。雖然橫向提權(quán)也很有威脅性但本文聚焦的是縱向這一類因?yàn)樗奈:Ω?、技術(shù)上也更典型。2.2 兩類提權(quán)溢出提權(quán)和第三方組件提權(quán)雖然提權(quán)的技術(shù)細(xì)節(jié)千變?nèi)f化但如果從“借助什么來(lái)提權(quán)”這個(gè)角度看可以很自然地分成兩大類溢出提權(quán)核心是“打破內(nèi)存邊界”。這類攻擊利用操作系統(tǒng)或應(yīng)用程序在處理數(shù)據(jù)時(shí)對(duì)內(nèi)存邊界檢查不嚴(yán)的缺陷通過(guò)精心構(gòu)造的輸入數(shù)據(jù)讓程序把惡意代碼寫入了本不該寫入的內(nèi)存區(qū)域進(jìn)而劫持程序執(zhí)行流程。成功之后惡意代碼就以目標(biāo)程序的權(quán)限運(yùn)行——如果目標(biāo)程序是以管理員或SYSTEM身份運(yùn)行的攻擊者的權(quán)限就跟著水漲船高。第三方組件提權(quán)核心是“利用受信任的幫手”。系統(tǒng)中通常運(yùn)行著大量服務(wù)或組件這些組件為了完成自身功能往往被賦予了較高的權(quán)限。攻擊者并不直接攻擊操作系統(tǒng)內(nèi)核而是轉(zhuǎn)頭去攻擊這些“高權(quán)限組件”通過(guò)組件本身的漏洞、錯(cuò)誤配置或者脆弱接口讓組件替自己執(zhí)行高權(quán)限操作。這類方式不依賴內(nèi)存破壞更多是“借力打力”。這兩條路線在現(xiàn)實(shí)中其實(shí)是交叉出現(xiàn)的一個(gè)溢出漏洞可能位于某個(gè)第三方組件里一個(gè)第三方組件被攻破之后后續(xù)也可能借助溢出手段繼續(xù)突破隔離。不過(guò)作為認(rèn)知框架把它們分開(kāi)講更容易建立清晰的思路所以后面的章節(jié)會(huì)分別深入。3. 深入第一大類溢出提權(quán)的原理與實(shí)戰(zhàn)形態(tài)3.1 溢出漏洞為什么存在內(nèi)存管理的信任困境要理解溢出提權(quán)必須先理解內(nèi)存和CPU打交道的方式。程序運(yùn)行的時(shí)候數(shù)據(jù)被存放在內(nèi)存的不同區(qū)域里其中有一個(gè)區(qū)域叫“?!盨tack它專門用來(lái)存放函數(shù)調(diào)用時(shí)的局部變量、返回地址等臨時(shí)數(shù)據(jù)。還有一個(gè)區(qū)域叫“堆”Heap用來(lái)存放程序運(yùn)行時(shí)動(dòng)態(tài)申請(qǐng)的內(nèi)存塊。問(wèn)題出在很多編程語(yǔ)言尤其是C/C里對(duì)內(nèi)存的訪問(wèn)是高度信任的程序說(shuō)這塊數(shù)據(jù)要放在某個(gè)緩沖區(qū)里系統(tǒng)就相信這個(gè)緩沖區(qū)夠大不會(huì)做越界檢查。打個(gè)生活化的比方你租了一個(gè)能放100件貨的倉(cāng)庫(kù)但管理員既不數(shù)數(shù)也不查單據(jù)你說(shuō)要往里面卸200件貨他也照單全收——多余的那100件就堆到了隔壁倉(cāng)庫(kù)的位置上。這個(gè)“隔壁倉(cāng)庫(kù)”如果放的是關(guān)鍵貨物那就會(huì)出大亂子。在內(nèi)存模型里這個(gè)“隔壁倉(cāng)庫(kù)”往往就是函數(shù)的返回地址、函數(shù)指針或者對(duì)象的方法表。攻擊者構(gòu)造的超長(zhǎng)輸入數(shù)據(jù)會(huì)一路溢出緩沖區(qū)最終精確地覆蓋掉返回地址。等到函數(shù)執(zhí)行完畢準(zhǔn)備返回時(shí)程序就會(huì)按照被篡改的地址跳轉(zhuǎn)——跳轉(zhuǎn)目標(biāo)通常是攻擊者事先布置好的惡意代碼。這樣一來(lái)程序的執(zhí)行流就完全落入了攻擊者的掌控。3.2 棧溢出和堆溢出兩種典型形態(tài)棧溢出是最經(jīng)典的一種形態(tài)原理就是我上面說(shuō)的那樣向棧上的緩沖區(qū)寫入過(guò)量數(shù)據(jù)覆蓋掉保存在棧幀里的返回地址。早年間很多系統(tǒng)服務(wù)漏洞都是這種類型。這類漏洞利用起來(lái)相對(duì)“直接”但現(xiàn)代操作系統(tǒng)普遍加入了棧保護(hù)機(jī)制比如在返回地址前插入一個(gè)隨機(jī)數(shù)函數(shù)返回前檢查這個(gè)隨機(jī)數(shù)有沒(méi)有被改動(dòng)這讓傳統(tǒng)的棧溢出利用變得困難了一些。堆溢出則稍微繞一點(diǎn)。堆不像棧那樣有嚴(yán)格的LIFO順序它的分配和釋放是動(dòng)態(tài)的。攻擊者溢出堆緩沖區(qū)之后通常需要想辦法覆蓋堆上某個(gè)關(guān)鍵對(duì)象的成員數(shù)據(jù)比如一個(gè)函數(shù)指針、一個(gè)長(zhǎng)度字段或者通過(guò)“堆風(fēng)水”把堆布局布置成對(duì)自己有利的形狀。堆溢出的利用難度通常比棧溢出高但因?yàn)槎训氖褂脠?chǎng)景非常廣泛實(shí)際出現(xiàn)的漏洞數(shù)量并不少。不管是棧還是堆溢出提權(quán)的關(guān)鍵前提有兩個(gè)一是存在一個(gè)以高權(quán)限運(yùn)行的進(jìn)程二是這個(gè)進(jìn)程處理外部輸入時(shí)存在內(nèi)存邊界缺陷。這兩個(gè)前提缺一不可。很多攻擊者會(huì)花大量精力去尋找“高權(quán)限進(jìn)程”里的“可通過(guò)網(wǎng)絡(luò)或本地接口觸達(dá)的缺陷”的目標(biāo)。3.3 現(xiàn)實(shí)中的溢出提權(quán)案例復(fù)盤我不說(shuō)具體版本號(hào)因?yàn)檫@類信息更新得太快說(shuō)多了反而容易誤導(dǎo)。但現(xiàn)實(shí)中的溢出提權(quán)案例大致有幾種典型場(chǎng)景場(chǎng)景A系統(tǒng)服務(wù)漏洞。某個(gè)系統(tǒng)自帶的打印服務(wù)、計(jì)劃任務(wù)服務(wù)或者內(nèi)核驅(qū)動(dòng)在處理特定格式的請(qǐng)求時(shí)存在溢出漏洞。這些服務(wù)通常以高權(quán)限運(yùn)行攻擊者只需要在本地或遠(yuǎn)程發(fā)一個(gè)精心構(gòu)造的請(qǐng)求就能觸發(fā)漏洞。早年很多“一鍵提權(quán)工具”利用的就是這類系統(tǒng)服務(wù)漏洞。場(chǎng)景B軟件邏輯漏洞。某個(gè)圖形界面程序在解析圖片文件、字體文件或文檔時(shí)存在溢出問(wèn)題。這類程序雖然平時(shí)以普通用戶運(yùn)行但某些組件比如預(yù)覽進(jìn)程、縮略圖生成服務(wù)可能以更高權(quán)限運(yùn)行。攻擊者構(gòu)造一個(gè)惡意文件誘騙管理員或高權(quán)限用戶打開(kāi)就能完成提權(quán)。場(chǎng)景C內(nèi)核驅(qū)動(dòng)缺陷。內(nèi)核里一個(gè)驅(qū)動(dòng)在處理輸入輸出控制IOCTL請(qǐng)求時(shí)沒(méi)有正確校驗(yàn)輸入緩沖區(qū)的大小。攻擊者通過(guò)普通用戶權(quán)限發(fā)起特殊請(qǐng)求觸發(fā)內(nèi)核態(tài)溢出從而拿到內(nèi)核權(quán)限。這類是最危險(xiǎn)的因?yàn)閮?nèi)核權(quán)限意味著系統(tǒng)上沒(méi)有任何東西能限制攻擊者。你得注意到這些場(chǎng)景的共同特點(diǎn)是攻擊者手里不一定有0day漏洞。很多時(shí)候系統(tǒng)沒(méi)打補(bǔ)丁、版本太舊、或者管理員安裝了不安全的第三方驅(qū)動(dòng)都能讓攻擊者直接使用公開(kāi)的漏洞利用代碼。所以從防守角度講溢出提權(quán)最有效的防御措施反而是最樸素的及時(shí)打補(bǔ)丁、減少不必要的系統(tǒng)組件、嚴(yán)格審核驅(qū)動(dòng)的來(lái)源。3.4 開(kāi)發(fā)者視角如何寫出不容易被溢出的代碼如果你是開(kāi)發(fā)者記住幾個(gè)基本法則能極大降低你寫的程序成為提權(quán)跳板的概率永遠(yuǎn)不要用不安全的字符串和內(nèi)存處理函數(shù)。比如經(jīng)典的strcpy、sprintf、gets它們不檢查目標(biāo)緩沖區(qū)長(zhǎng)度是緩沖區(qū)溢出的重災(zāi)區(qū)?,F(xiàn)代編譯器的安全函數(shù)庫(kù)或C的標(biāo)準(zhǔn)庫(kù)容器能在很大程度上規(guī)避這類問(wèn)題。對(duì)解析輸入數(shù)據(jù)的代碼保持高度警惕。解析網(wǎng)絡(luò)協(xié)議、文件格式、壓縮數(shù)據(jù)的代碼是溢出漏洞的高發(fā)區(qū)因?yàn)檫@些代碼要處理不可信的輸入而且經(jīng)常涉及復(fù)雜的長(zhǎng)度計(jì)算。凡是這類代碼都要做嚴(yán)格的邊界檢查并引入單元測(cè)試和模糊測(cè)試。使用內(nèi)存安全的語(yǔ)言處理高風(fēng)險(xiǎn)模塊。如果項(xiàng)目允許在解析不可信輸入的模塊里優(yōu)先考慮使用帶自動(dòng)內(nèi)存管理的語(yǔ)言比如Rust、Go、Java或者把C/C模塊放進(jìn)沙箱里運(yùn)行。這里我多說(shuō)一句很多開(kāi)發(fā)者覺(jué)得“編譯器開(kāi)幾個(gè)安全選項(xiàng)”就夠了其實(shí)遠(yuǎn)遠(yuǎn)不夠。比如棧保護(hù)Stack Canary確實(shí)能擋住一部分棧溢出利用但對(duì)堆溢出、以及某些繞過(guò)棧保護(hù)的利用手法就力不從心了。真正靠譜的思路是從源頭上減少內(nèi)存不安全操作而不是依賴編譯器兜底。4. 深入第二大類第三方組件提權(quán)的原理與實(shí)操分析4.1 第三方組件為什么容易成為提權(quán)跳板如果說(shuō)溢出提權(quán)是“硬碰硬”地突破系統(tǒng)邊界那第三方組件提權(quán)就是“找軟肋”地繞開(kāi)系統(tǒng)邊界?,F(xiàn)實(shí)中我見(jiàn)過(guò)的提權(quán)攻擊很大一部分走的都是第三方組件這條路因?yàn)樗某晒β释?。什么叫第三方組件就是那些不是你自己的系統(tǒng)代碼而是外部引入的服務(wù)、插件、驅(qū)動(dòng)、中間件。例如某些企業(yè)的內(nèi)網(wǎng)環(huán)境里IT部門為了方便管理會(huì)上一些遠(yuǎn)程支持工具、終端管理軟件、備份代理服務(wù)。這些軟件為了保證功能正常經(jīng)常會(huì)以系統(tǒng)權(quán)限運(yùn)行或者在本地開(kāi)啟一個(gè)高權(quán)限的服務(wù)端口。問(wèn)題在于這些第三方組件往往不像操作系統(tǒng)本身那樣經(jīng)過(guò)嚴(yán)格的攻防測(cè)試加上它們的更新機(jī)制參差不齊很容易留下漏洞窗口。攻擊者的思路很直接他不需要和操作系統(tǒng)硬拼只需要找到這個(gè)“高權(quán)限的第三方組件”然后想辦法讓組件替自己執(zhí)行命令就可以了。這有點(diǎn)像你不去撬銀行金庫(kù)的保險(xiǎn)柜而是找到一個(gè)有金庫(kù)鑰匙的保安想辦法讓保安幫你打開(kāi)門——保安就是那個(gè)高權(quán)限組件。4.2 第三方組件的典型漏洞形態(tài)第三方組件提權(quán)的實(shí)現(xiàn)方式比溢出提權(quán)更多樣常見(jiàn)的漏洞形態(tài)有這么幾類第一類命令注入。組件在執(zhí)行某個(gè)功能時(shí)會(huì)把外部輸入拼接到系統(tǒng)命令里。如果輸入沒(méi)有經(jīng)過(guò)嚴(yán)格過(guò)濾攻擊者就能通過(guò)特殊字符比如分號(hào)、管道符號(hào)注入自己想要的命令。很多管理類組件都存在這類問(wèn)題。第二類不安全的反序列化。組件在接收序列化數(shù)據(jù)并還原成對(duì)象的過(guò)程中如果缺少類型過(guò)濾攻擊者可以構(gòu)造惡意的序列化數(shù)據(jù)觸發(fā)任意代碼執(zhí)行。這在很多使用Java、Python、PHP編寫的中間件里特別常見(jiàn)。第三類錯(cuò)誤的權(quán)限配置。組件本身沒(méi)有漏洞但安裝者的配置有問(wèn)題。比如給某個(gè)服務(wù)目錄設(shè)置了對(duì)所有人可寫的權(quán)限或者給一個(gè)本應(yīng)只在本機(jī)調(diào)用的管理接口開(kāi)了網(wǎng)絡(luò)監(jiān)聽(tīng)甚至監(jiān)聽(tīng)端口還用了弱口令。這類問(wèn)題不需要攻擊者有很高的技術(shù)水平但攻擊效果往往立竿見(jiàn)影。第四類缺失身份認(rèn)證的接口。某些組件為了方便集成會(huì)提供本機(jī)調(diào)用的API接口默認(rèn)不做認(rèn)證。攻擊者只需要從本地發(fā)一個(gè)簡(jiǎn)單的HTTP請(qǐng)求就能讓組件執(zhí)行高權(quán)限操作。我見(jiàn)過(guò)一個(gè)很典型的案例某企業(yè)的終端管理軟件在每臺(tái)機(jī)器上裝了一個(gè)Agent服務(wù)這個(gè)Agent以SYSTEM權(quán)限運(yùn)行同時(shí)還開(kāi)放了一個(gè)本地端口用于接受管理指令。問(wèn)題是這個(gè)端口完全沒(méi)有做認(rèn)證任何人只要在本機(jī)上連一下這個(gè)端口發(fā)送一段簡(jiǎn)單的指令A(yù)gent就會(huì)乖乖地以SYSTEM權(quán)限去執(zhí)行命令。整個(gè)提權(quán)過(guò)程不需要任何漏洞利用代碼只需要知道那個(gè)端口號(hào)和幾個(gè)指令格式而已。這就是第三方組件提權(quán)里最“傻瓜式”、也最讓人頭疼的一種——它壓根不需要打補(bǔ)丁能解決因?yàn)檫@是設(shè)計(jì)上的信任缺陷。4.3 為什么第三方組件漏洞在李鬼式攻擊里特別流行提到第三方組件提權(quán)大家最熟悉的領(lǐng)域其實(shí)是各種非官方渠道流傳的“綠色版”“優(yōu)化版”“一鍵版”組件。很多用戶圖省事從非官方渠道下載了被加工過(guò)的組件包安裝之后才發(fā)現(xiàn)里面藏著惡意代碼。這些代碼平時(shí)潛伏不動(dòng)等到檢測(cè)到系統(tǒng)處于低權(quán)限狀態(tài)時(shí)就會(huì)利用組件自身的特權(quán)完成提權(quán)。這種現(xiàn)象防不勝防的原因在于第三方組件的供應(yīng)鏈?zhǔn)欠浅?fù)雜的開(kāi)發(fā)者從A庫(kù)引用了B庫(kù)B庫(kù)又依賴了C庫(kù)只要鏈條上任何一個(gè)環(huán)節(jié)出了問(wèn)題最終產(chǎn)品都會(huì)受到牽連。這幾年業(yè)界對(duì)軟件供應(yīng)鏈安全的關(guān)注度明顯上升但對(duì)很多中小團(tuán)隊(duì)來(lái)說(shuō)真正把依賴管理做起來(lái)、把第三方組件的來(lái)源控制住仍然是一件知易行難的事。4.4 開(kāi)發(fā)者和運(yùn)維者怎么防第三方組件提權(quán)防第三方組件提權(quán)的核心思路可以總結(jié)成四個(gè)關(guān)鍵詞最小化、隔離、驗(yàn)證、監(jiān)控。最小化能不裝第三方組件就不裝尤其是不裝那些功能冗余、權(quán)限要求過(guò)高的管理類工具。每多一個(gè)組件就多一分被攻擊的風(fēng)險(xiǎn)面。裝之前先問(wèn)問(wèn)自己這個(gè)組件真的需要嗎它提供的功能有沒(méi)有系統(tǒng)自帶的替代方案隔離如果必須裝那么盡量把組件放進(jìn)低權(quán)限的上下文里運(yùn)行。比如不要讓組件以SYSTEM權(quán)限運(yùn)行能用普通服務(wù)賬號(hào)就用普通服務(wù)賬號(hào)能放在容器里就放容器里能關(guān)掉網(wǎng)絡(luò)監(jiān)聽(tīng)就關(guān)掉。隔離的核心原則是“讓組件即使被攻破它手里的權(quán)限也是非常有限的”。驗(yàn)證定期檢查第三方組件的版本和漏洞通告建立一版“組件資產(chǎn)清單”對(duì)照廠商的修復(fù)公告及時(shí)更新。重點(diǎn)是自動(dòng)化——手工去記每個(gè)組件裝在哪臺(tái)機(jī)器上是不現(xiàn)實(shí)的一定要有資產(chǎn)盤點(diǎn)工具。監(jiān)控在組件運(yùn)行路徑上埋監(jiān)控點(diǎn)。比如對(duì)高權(quán)限組件的啟動(dòng)參數(shù)、它訪問(wèn)的敏感路徑、它發(fā)起的網(wǎng)絡(luò)連接做審計(jì)和告警。攻擊者利用組件提權(quán)的時(shí)候一定會(huì)有異常行為監(jiān)控的價(jià)值就是讓這些異常暴露出來(lái)。5. 兩類提權(quán)的橫向?qū)Ρ裙舫杀?、檢測(cè)難度與防護(hù)側(cè)重5.1 攻擊者視角的對(duì)比我試著從攻擊成本的角度把溢出提權(quán)和第三方組件提權(quán)放到一張表里你可能一下子就能看出兩者的區(qū)別對(duì)比維度溢出提權(quán)第三方組件提權(quán)技術(shù)門檻高需要深入理解內(nèi)存布局、繞過(guò)防護(hù)機(jī)制相對(duì)較低很多是配置利用和接口濫用前期依賴依賴目標(biāo)系統(tǒng)或軟件的未修復(fù)漏洞依賴目標(biāo)是否安裝特定組件及組件的缺陷漏洞獲取成本高0day價(jià)格昂貴Nday需要碰運(yùn)氣低組件漏洞往往公開(kāi)在通告里且組件版本參差不齊成功后的隱蔽性較高內(nèi)核態(tài)溢出尤其難以追溯較低組件本身會(huì)有運(yùn)行日志但很多環(huán)境根本不看日志可靠性受目標(biāo)系統(tǒng)版本、加固情況影響大相對(duì)穩(wěn)定配置缺陷通常不因微小的系統(tǒng)補(bǔ)丁而改變這張表能解釋很多現(xiàn)實(shí)觀察大規(guī)模掃描和自動(dòng)化攻擊工具里第三方組件漏洞的利用率遠(yuǎn)高于溢出漏洞。因?yàn)閷?duì)攻擊者來(lái)說(shuō)掃描“某個(gè)端口對(duì)應(yīng)的組件是否存在已知漏洞”比“判斷某個(gè)程序是否存在可利用的溢出”要容易得多。溢出漏洞通常需要專門針對(duì)特定版本的定向利用而第三方組件的配置缺陷和已知漏洞是批量打的。5.2 防守方視角的應(yīng)對(duì)差異防守方在兩類提權(quán)上的側(cè)重點(diǎn)也應(yīng)該不一樣對(duì)溢出提權(quán)重點(diǎn)放在補(bǔ)丁管理和系統(tǒng)加固上。操作系統(tǒng)和核心軟件的補(bǔ)丁及時(shí)打上就能堵住絕大多數(shù)已知的溢出利用開(kāi)啟系統(tǒng)的強(qiáng)制性防護(hù)機(jī)制比如進(jìn)程隔離、數(shù)據(jù)執(zhí)行保護(hù)、地址空間布局隨機(jī)化即便出現(xiàn)0day漏洞利用難度也會(huì)大幅提升。對(duì)第三方組件提權(quán)重點(diǎn)放在資產(chǎn)盤點(diǎn)和權(quán)限收斂上。你得先知道自己的環(huán)境里裝了哪些第三方組件它們以什么權(quán)限運(yùn)行、開(kāi)放了哪些端口、有沒(méi)有不必要的管理接口。只有先盤出來(lái)才談得上控制風(fēng)險(xiǎn)。從實(shí)際防御優(yōu)先級(jí)來(lái)看我個(gè)人的經(jīng)驗(yàn)是對(duì)大多數(shù)企業(yè)來(lái)說(shuō)第三方組件提權(quán)反而是更緊迫的那個(gè)問(wèn)題。因?yàn)橄到y(tǒng)補(bǔ)丁很多人還能記得打但第三方組件的補(bǔ)丁和權(quán)限配置經(jīng)常被完全遺忘。我見(jiàn)過(guò)不少環(huán)境操作系統(tǒng)補(bǔ)丁打得非常勤但某個(gè)業(yè)務(wù)團(tuán)隊(duì)自己裝的輔助工具兩三年沒(méi)更新過(guò)上面掛著公開(kāi)的遠(yuǎn)程代碼執(zhí)行漏洞。這種“短板效應(yīng)”在防守層面比溢出漏洞更致命。6. 實(shí)操實(shí)錄一次典型提權(quán)鏈路的完整復(fù)盤6.1 場(chǎng)景設(shè)定為了把兩類提權(quán)如何串聯(lián)起來(lái)講清楚我模擬一個(gè)非常典型的攻擊場(chǎng)景整個(gè)過(guò)程基于我在攻防演練里反復(fù)見(jiàn)過(guò)的真實(shí)套路目標(biāo)環(huán)境某內(nèi)網(wǎng)Windows服務(wù)器安裝了某第三方文件管理工具用于業(yè)務(wù)文件交互。攻擊者起點(diǎn)通過(guò)員工終端上的釣魚郵件拿到了一個(gè)普通域賬號(hào)。攻擊目標(biāo)拿到服務(wù)器的本地管理員權(quán)限。6.2 鏈路一通過(guò)第三方組件完成第一步提權(quán)攻擊者用普通域賬號(hào)遠(yuǎn)程登錄到目標(biāo)服務(wù)器有遠(yuǎn)程桌面權(quán)限打開(kāi)命令行執(zhí)行了一組簡(jiǎn)單指令。他先查了一下系統(tǒng)上有哪些正在運(yùn)行的第三方服務(wù)果然看到了那個(gè)文件管理工具的服務(wù)進(jìn)程而且進(jìn)程的運(yùn)行身份是“本地系統(tǒng)”SYSTEM。他接著檢查工具的本機(jī)管理端口。結(jié)果發(fā)現(xiàn)這個(gè)端口果然沒(méi)有做訪問(wèn)控制任何人都能直接發(fā)送指令。他發(fā)送了一條文件下載指令讓工具從攻擊者控制的服務(wù)器上下載一個(gè)惡意腳本到本地然后再發(fā)送一條“執(zhí)行腳本”的指令。整個(gè)過(guò)程簡(jiǎn)潔高效惡意腳本就以SYSTEM權(quán)限運(yùn)行了。到這里攻擊者沒(méi)有觸發(fā)任何溢出漏洞也沒(méi)有用到任何0day僅僅是因?yàn)榈谌浇M件在設(shè)計(jì)和部署時(shí)存在兩個(gè)問(wèn)題——權(quán)限過(guò)高、接口無(wú)認(rèn)證。6.3 鏈路二通過(guò)溢出利用完成進(jìn)一步的權(quán)限突破在第一個(gè)場(chǎng)景里攻擊者已經(jīng)拿到了SYSTEM權(quán)限其實(shí)已經(jīng)“通關(guān)”了。但如果目標(biāo)系統(tǒng)的安全配置更好一些第三方組件被降權(quán)運(yùn)行、管理接口也加了認(rèn)證攻擊者就會(huì)轉(zhuǎn)入第二條路——溢出提權(quán)。假設(shè)攻擊者在服務(wù)器上發(fā)現(xiàn)了一個(gè)版本較舊的服務(wù)這個(gè)服務(wù)以管理員權(quán)限運(yùn)行且存在一個(gè)緩沖區(qū)溢出漏洞。攻擊者在本地寫了一個(gè)小工具向該服務(wù)發(fā)送構(gòu)造好的異常請(qǐng)求。服務(wù)在處理請(qǐng)求時(shí)發(fā)生了內(nèi)存越界攻擊者的代碼被執(zhí)行。由于服務(wù)本身是管理員權(quán)限攻擊者順理成章地完成了從普通用戶到管理員權(quán)限的跨越?,F(xiàn)實(shí)中這兩條鏈路經(jīng)常是交叉的攻擊者可能先用溢出漏洞搞定一個(gè)低權(quán)限進(jìn)程再去攻擊第三方組件也可能先拿下第三方組件再用組件的能力去加載驅(qū)動(dòng)、關(guān)閉防護(hù)軟件。鏈路本身怎么走不重要重要的是你明白了每一個(gè)節(jié)點(diǎn)的“權(quán)限變化”是怎么發(fā)生的。6.4 防守視角的完整排查清單站在防守方的角度針對(duì)上面這個(gè)場(chǎng)景我總結(jié)了一份排查清單你可以直接拿去用第一步識(shí)別高權(quán)限組件。用任務(wù)管理器或命令行工具列出系統(tǒng)所有正在運(yùn)行的進(jìn)程重點(diǎn)標(biāo)記“以管理員或SYSTEM身份運(yùn)行”的進(jìn)程挨個(gè)確認(rèn)它們的來(lái)源和必要性。這一步的產(chǎn)出是“高權(quán)限進(jìn)程清單”。第二步檢查本地開(kāi)放端口。用netstat查看系統(tǒng)所有處于監(jiān)聽(tīng)狀態(tài)的端口檢查哪些端口是第三方組件開(kāi)放的。對(duì)于每個(gè)端口確認(rèn)它是否真的需要對(duì)外開(kāi)放是否做了身份認(rèn)證。特別是那些只綁定在127.0.0.1上的端口很多運(yùn)維覺(jué)得“本機(jī)端口沒(méi)人能訪問(wèn)”就疏于防護(hù)其實(shí)是誤解——一旦攻擊者已經(jīng)獲得了本機(jī)任意低權(quán)限代碼執(zhí)行能力本機(jī)端口就等于對(duì)攻擊者開(kāi)放。第三步確認(rèn)組件版本與補(bǔ)丁狀態(tài)。對(duì)照組件清單去檢查每個(gè)組件的版本號(hào)和已知漏洞通告。這一步要形成定期巡檢的機(jī)制不能靠記憶。第四步檢查目錄與文件權(quán)限。查看第三方組件的安裝目錄、配置文件的訪問(wèn)控制列表確認(rèn)不存在“Everyone可寫”之類的問(wèn)題。惡意攻擊者經(jīng)常通過(guò)修改組件的配置文件或替換組件目錄下的可執(zhí)行文件來(lái)完成提權(quán)。第五步審計(jì)異常行為。在系統(tǒng)的安全日志和組件的運(yùn)行日志里搜索可疑的命令執(zhí)行記錄、非授權(quán)訪問(wèn)記錄。重點(diǎn)看高權(quán)限進(jìn)程是否執(zhí)行過(guò)與自身功能無(wú)關(guān)的程序。7. 常見(jiàn)問(wèn)題與排查技巧實(shí)錄7.1 為什么我打了所有系統(tǒng)補(bǔ)丁還是被提權(quán)了這是我在工作中被問(wèn)到最多的問(wèn)題。答案通常不在“系統(tǒng)補(bǔ)丁”這個(gè)層面而在“你沒(méi)納入補(bǔ)丁體系的東西”上。很多第三方組件有自己的更新機(jī)制甚至有些組件因?yàn)闃I(yè)務(wù)兼容性原因被運(yùn)維主動(dòng)固定住版本不升級(jí)。攻擊者掃描到的就是這個(gè)“版本固定”的組件。我見(jiàn)過(guò)不少環(huán)境操作系統(tǒng)補(bǔ)丁一個(gè)月不落但內(nèi)網(wǎng)里跑著一個(gè)三年前版本的中間件上面掛著一堆公開(kāi)漏洞。排查技巧不要只做操作系統(tǒng)層面的補(bǔ)丁檢查要做全量資產(chǎn)視角的補(bǔ)丁檢查。把系統(tǒng)里所有可執(zhí)行文件、服務(wù)、端口、安裝包全部盤點(diǎn)一遍和漏洞庫(kù)做對(duì)照。這一步最好用自動(dòng)化工具因?yàn)槭止じ居洸蛔∩习賯€(gè)組件的版本狀態(tài)。7.2 為什么我的組件沒(méi)有漏洞攻擊者還是能通過(guò)它提權(quán)沒(méi)有漏洞不代表沒(méi)有風(fēng)險(xiǎn)。我在前面講過(guò)“錯(cuò)誤的權(quán)限配置”“缺失認(rèn)證的接口”這類問(wèn)題它們不是“漏洞”而是“弱點(diǎn)”。漏洞要等廠商出補(bǔ)丁修復(fù)弱點(diǎn)只能靠你自己改配置修復(fù)。很多組件默認(rèn)配置是“開(kāi)箱即用、方便優(yōu)先”安全性排在很后面。你裝上組件之后不能保持默認(rèn)配置而應(yīng)該按最小權(quán)限原則逐項(xiàng)審查。排查技巧針對(duì)每個(gè)高權(quán)限組件反復(fù)問(wèn)三個(gè)問(wèn)題它必須以SYSTEM權(quán)限運(yùn)行嗎它必須監(jiān)聽(tīng)網(wǎng)絡(luò)端口嗎它必須接受非本機(jī)連接嗎任何一個(gè)回答是“不一定”就說(shuō)明存在權(quán)限收斂的空間。7.3 如何檢測(cè)系統(tǒng)里有沒(méi)有被植入提權(quán)后門這件事難度比較大但有一些基礎(chǔ)的排查思路檢查系統(tǒng)計(jì)劃任務(wù)里有沒(méi)有異常項(xiàng)檢查啟動(dòng)項(xiàng)和服務(wù)里有沒(méi)有名字偽裝成系統(tǒng)組件的可疑程序檢查用戶賬戶列表里有沒(méi)有多出來(lái)的隱藏賬戶。這些是“結(jié)果側(cè)”的檢查。更主動(dòng)的方式是“行為側(cè)”的檢查讓監(jiān)控系統(tǒng)記錄高權(quán)限進(jìn)程的父子關(guān)系、加載模塊的情況。我自己比較推薦的方式是定期做一次全盤“進(jìn)程白名單”比對(duì)把所有運(yùn)行中的進(jìn)程和已知的合法進(jìn)程清單做對(duì)比差異項(xiàng)就是重點(diǎn)關(guān)注對(duì)象。7.4 我對(duì)提權(quán)攻擊的一些獨(dú)家實(shí)操心得最后分享幾條我個(gè)人在實(shí)際攻防對(duì)抗中積累的心得這些不太會(huì)寫在教科書里心得一優(yōu)先盯“以SYSTEM身份運(yùn)行的第三方進(jìn)程”。系統(tǒng)自帶的進(jìn)程雖然也是高權(quán)限但它們的補(bǔ)丁路徑通常很清晰反而是那些以SYSTEM運(yùn)行的第三方進(jìn)程權(quán)限高、補(bǔ)丁散、配置亂是提權(quán)攻擊的重災(zāi)區(qū)。心得二本機(jī)端口掃描比你想象中更有用。很多安全團(tuán)隊(duì)把精力花在網(wǎng)絡(luò)邊界掃描上忽略了每臺(tái)終端本身的本地監(jiān)聽(tīng)端口。攻擊者到了內(nèi)網(wǎng)之后第一步往往就是掃本機(jī)和內(nèi)網(wǎng)鄰接設(shè)備的端口。防守方完全可以學(xué)這個(gè)思路定期對(duì)內(nèi)部所有主機(jī)做一次端口掃描重點(diǎn)關(guān)注非標(biāo)準(zhǔn)端口、非官方組件的監(jiān)聽(tīng)端口。心得三低權(quán)限環(huán)境隔離是最后一道防線。就算前面所有防線都被突破了如果組件之間做了權(quán)限隔離攻擊者拿到的還只是“單個(gè)組件的權(quán)限”而不是“整個(gè)系統(tǒng)的權(quán)限”。我在實(shí)際參與的項(xiàng)目中吃過(guò)虧也嘗過(guò)甜頭凡是做了組件隔離的環(huán)境即使發(fā)生提權(quán)攻擊影響范圍也能被壓縮到一個(gè)很小的圈子里。這個(gè)思路放在現(xiàn)在越發(fā)重要因?yàn)閱渭兊摹按蜓a(bǔ)丁”很難做到百分百及時(shí)但隔離是穩(wěn)賺不賠的策略。心得四日志別光“存”要“看”。很多環(huán)境的日志系統(tǒng)都有但告警規(guī)則粗糙得形同虛設(shè)。高權(quán)限進(jìn)程突然啟動(dòng)一個(gè)子進(jìn)程、一個(gè)本不該聯(lián)網(wǎng)的組件發(fā)起了外聯(lián)、一個(gè)服務(wù)賬號(hào)在凌晨執(zhí)行了命令——這些如果靠人工翻日志根本翻不過(guò)來(lái)但靠規(guī)則告警就很容易捕捉。把日志告警的規(guī)則做細(xì)比盲目增加日志量有用得多。8. 寫在最后提權(quán)攻防的本質(zhì)與長(zhǎng)期應(yīng)對(duì)思路提到這里兩類提權(quán)方式的內(nèi)外邏輯已經(jīng)比較清楚了。溢出提權(quán)告訴你“內(nèi)存邊界不能隨便信任”第三方組件提權(quán)告訴你“外來(lái)的幫手可能并不安全”。兩者殊途同歸最后都指向同一個(gè)核心問(wèn)題系統(tǒng)里每一個(gè)高權(quán)限的運(yùn)行單元都必須被清清楚楚地看到、嚴(yán)格地制約住。我在實(shí)際工作中反復(fù)體會(huì)到真正難的不是知道某一個(gè)具體漏洞的利用原理而是建立起一整套“權(quán)限意識(shí)”。開(kāi)發(fā)同學(xué)寫代碼的時(shí)候要知道自己調(diào)用的庫(kù)可能被濫用運(yùn)維同學(xué)部署組件的時(shí)候要知道多開(kāi)一個(gè)端口就多一條被提權(quán)的路安全同學(xué)做巡檢的時(shí)候要知道系統(tǒng)里哪些進(jìn)程是高權(quán)限的、它們?yōu)槭裁词歉邫?quán)限的、可不可以收斂到更低的權(quán)限。這個(gè)領(lǐng)域的技術(shù)變化很快今天的具體漏洞和組件名字過(guò)幾個(gè)月可能就被新的替代了。但只要抓住了“權(quán)限邊界”這個(gè)核心所有新的攻擊手法在你眼里都不過(guò)是舊瓶裝新酒。在防守上我個(gè)人的體會(huì)是扎實(shí)的基礎(chǔ)運(yùn)維比花哨的安全產(chǎn)品更能防住提權(quán)攻擊。把補(bǔ)丁打全、把端口收住、把組件權(quán)限降下來(lái)、把日志告警調(diào)好——這些事聽(tīng)著樸素但恰恰是絕大多數(shù)提權(quán)攻擊的最大阻礙。如果你看完這篇文章能回去把自己管理的系統(tǒng)里所有高權(quán)限進(jìn)程盤一遍、把第三方組件的配置逐項(xiàng)收緊一遍那我這幾千字就算沒(méi)白寫。至于更細(xì)的動(dòng)態(tài)攻防對(duì)抗那是另一篇文章的話題了有機(jī)會(huì)再聊。