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