作者:yyjb@360高級攻防實驗室
原文鏈接:http://noahblog.#/cve-2021-1675/
背景
本月的微軟更新包含一個spool的打印機服務本地提權漏洞,自從去年cve-2020-1048被公開以來,似乎許多人開始關注到這一模塊的漏洞。鑒于此這個漏洞剛公布出來時,并沒有太仔細關注。直到后面關注到綠盟的微信公眾號的演示視頻,顯示這個漏洞可能在域環境特定情況下執行任意代碼。所以認為有必要對其原理以及適用范圍情況進行分析。
補丁分析
通過補丁對比,可以確定該漏洞觸發原理應該是一個在添加打印機驅動的過程中RpcAddPrinterDriverEx()繞過某些檢查的漏洞。

根據API文檔,RpcAddPrinterDriverEx API用于在打印機服務器上安裝打印機驅動;第三個參數為dwFileCopyFlags,指定了服務器在拷貝驅動文件時的行為。文檔給出了標志的可能值,結合補丁,我們發現了這樣一個標志:APD_INSTALL_WARNED_DRIVER(0x8000),此標志允許服務器安裝警告的打印機驅動,也就是說,如果在flag中設置了APD_INSTALL_WARNED_DRIVER,那么我們可以無視警告安裝打印機驅動。這剛好是微軟補丁試圖限制的標志位。

本地提權
我們分析了添加驅動的內部實現(位于localspl.dll的InternalAddPrinterDriver函數),添加驅動的過程如下:
-
檢查驅動簽名
-
建立驅動文件列表
-
檢查驅動兼容性
-
拷貝驅動文件
如果能夠繞過其中的限制,將自己編寫的dll復制到驅動目錄并加載,就可以完成本地提權。

繞過對驅動文件簽名的檢查
繞過驅動簽名檢查的關鍵函數為ValidateDriverInfo()。分析該函數,我們發現,如果標志位設置了APD_INSTALL_WARNED_DRIVER(0x8000),那么函數會跳過驅動路徑和驅動簽名的檢查。

繞過建立驅動文件目錄函數
CreateInternalDriverFileArray()函數根據文件操作標志來決定是否檢查spool驅動目錄。如果a5 flag被標志為False,驅動加載函數只會檢查用戶目錄中是否包含要拷貝的驅動文件;否則,函數會嘗試到spool驅動目錄尋找目標驅動,在本地提權場景下,這將導致列表建立失敗。
通過簡單分析可以發現,在FileCopyFlags中設置APD_COPY_FROM_DIRECTORY(0x10),即可跳過spool目錄檢查。

繞過驅動文件版本檢查
后續的檢查包括對需要添加的驅動的兼容性檢查,這里主要是檢查我們需要添加的驅動版本信息(這里主要是指版本號的第二位,我后面所描述的版本號都特指第二位):
下面是用來被當去打印驅動加載的我們自己生成的一個dll文件,

修改dll文件版本號繞過驅動文件兼容性檢查:
驅動加載函數InternalAddPrinterDriver中的檢查限制了驅動版號只能為0,1,3.

而兼容性檢查的內部函數實現(ntprint.dll的PSetupIsCompatibleDriver函數)又限制了該版本號必須大于2。因此,可以修改待加載驅動或dll文件的版本號為3,從而繞過驅動兼容性檢查。

驅動文件的復制加載
驅動文件拷貝函數(CopyFileToFinalDirectory)對參數沒有額外的限制。函數執行完成后,我們的驅動文件以及依賴就被復制到驅動目錄了,復制后的驅動文件會被自動加載。

自動加載驅動:

嘗試遠程執行代碼。
目前,我們已經可以從本地指定的用戶目錄加載我們自定義的打印機驅動文件到spool驅動目錄。之前我們對AddPrinterDriverExW函數的調用第一個參數為空,用來在本地加載。如果直接設置該參數為指定服務器地址,目標會返回我們需要登陸到目標設備的權限的錯誤。作為測試,我們先通過IPC連接到目標設備,之后再通過我們的驅動添加調用,使遠程目標設備從其本地的指定目錄復制驅動文件到spool驅動目錄并加載。
但這里有一個問題,這個操作僅僅是讓目標服務器從本地磁盤復制并加載驅動,在此之前,我們還要使我們自己的驅動文件從攻擊機設備的目錄上分發到目標設備上。
這里就必須要求目標開啟對應的集群后臺打印處理程序,之后再次調用AddPrinterDriverExW修改標志為APD_COPY_TO_ALL_SPOOLERS,將本地的驅動文件分發到目標設備磁盤上。
遠程加載驅動
最后,我這里并沒有使用實際的集群打印服務器的環境。作為測試,我預先復制了驅動文件到目標服務器的指定路徑。調用AddPrinterDriverExW使遠程目標服務器完成了復制用戶目錄驅動文件到驅動目錄并以system權限加載的過程。
思路驗證視頻:

漏洞總結
該漏洞的核心是允許普通用戶繞過檢查,將一個任意未簽名dll復制到驅動目錄并以系統管理員權限加載起來。而該漏洞可以達到遠程觸發的效果,則是由于集群打印服務間可以遠程分發接收打印驅動文件的特性。
所以就目前的漏洞驗證結果來看,該漏洞的危害似乎可能比他的漏洞原理表現出來的要影響更多一點。除了作為本地提權的利用方式之外,如果在一些內部隔離辦公環境,啟用了這種集群打印服務又沒有及時更新系統補丁,該漏洞的作用還是比較有威脅性的。
對 PrintNightmare 0day POC的補充說明
通過最近一兩天其他研究人員的證明,目前公開的cube0x0/PrintNightmare poc可以對最新的補丁起作用。鑒于此,我們后續驗證了這個原因。
通過分析,補丁函數中對調用來源做了檢查,查詢當前調用者token失敗時,會強制刪除掉APD_INSTALL_WARNED_DRIVER(0x8000)的驅動添加標志。從而導致驗證不通過。

但是,當我們從遠程調用到這個接口,至少目前證實的通過IPC連接到目標后,這里的調用者已經繼承了所需要的token,從而繞過檢查。

從某種意義上講,該漏洞修復方案只針對本地提權場景進行了限制,而沒有考慮到遠程調用對漏洞的影響。
參考
https://mp.weixin.qq.com/s/MjLPFuFJobkDxaIowvta7A
https://github.com/cube0x0/CVE-2021-1675
本文由 Seebug Paper 發布,如需轉載請注明來源。本文地址:http://www.bjnorthway.com/1699/
暫無評論