作者:cheery@QAX-ATEAM && n0thing@QAX-ATEAM
公眾號: 奇安信ATEAM

0x00 前言

本文是由一次真實的授權滲透案例引申而出的技術分析和總結文章。在文章中我們會首先簡單介紹這次案例的整體滲透流程并進行部分演繹,但不會進行詳細的截圖和描述,一是怕“有心人”發現端倪去目標復現漏洞和破壞,二是作為一線攻擊人員,大家都明白滲透過程也是一個試錯過程,針對某一個點我們可能嘗試了無數種方法,最后寫入文章的只有成功的一種,而這種方法很有可能也是眾所周知的方法。因此我們只會簡單介紹滲透流程,然后提取整個滲透過程中比較精華的點,以點及面來進行技術分析和探討,望不同的人有不同的收獲。

0x01 滲透流程簡述

在接到項目以后,由“前端”小組(初步技術分析小組)進行項目分析和信息收集以及整理,整理出了一批域名和一些關鍵站點,其中有一個phpmyadmin 和 discuz的組合建站,且均暴露在外網,這也是很常見的一種情況。由于網站某個web端口的解析配置問題導致了php不被解析而形成任意文件下載漏洞,通過這個漏洞我們拿到了mysql的root賬戶密碼。由于linux服務器權限設置比較嚴格的問題沒法直接使用phpmyadmin登錄mysql而提權拿到discuz的webshell。經過多種嘗試我們利用phpmyadmin替換管理員hash而登錄discuz后臺,在discuz后臺利用修改ucenter配置文件的漏洞寫入了webshell。

在進入內網以后,通過簡單的80、443探測內網的web時候發現了一個含有java webdav的服務器(域內windows,后文中以A服務器稱呼),利用java webdav的xxe去執行NTLM Relay。同時收集discuz數據庫中用戶名利用kerberos AS_REQ和密碼噴射(一個密碼和不同用戶名的組合去KDC枚舉)幸運的獲得了一組域內用戶的賬戶和密碼,利用這個用戶增加了一個機器賬戶。結合NTLM Relay和這個機器賬戶利用基于資源的約束委派,成功的使這個機器賬戶具有了控制A服務器的權限。登錄A服務器繞過卡巴斯基抓取到了域管理密碼,這次攻堅任務也因此而結束。圖示如下:

在這次滲透流程中我們認為Discuz x3系列xxe到域控這兩個點是值得拿出來分析和探討的。

0x02 Discuz X3系列

本節分為3部分,首先將對Discuz X3以后的版本出現的主要漏洞做一個簡單總結,然后針對discuz的幾種密鑰做一些分析,最后發布一個discuz最新的后臺getshell

Discuz X3以后漏洞總結

目前市面上基本都是x3以上的Discuz程序了,x3以下的網站占比已經非常低了,因此在此只總結x3以上的漏洞。總結并不是對每個漏洞進行重新分析,這是沒有必要的,網上已經有很多優秀的分析文章了。那我們為什么還要總結呢?如果你是在一線做滲透測試或者紅隊評估的同學,應該會經常遇到discuz,往往大部分同學一看程序版本再搜搜漏洞或者群里問問就放棄了。在大家的印象中discuz是一塊硬骨頭,沒必要耗太多時間在它身上,但事實上discuz并不是你所想象的那么安全。本小節將通過總結discuz的各種小漏洞,再結合我們自己的幾次對discuz目標的突破,提出一些利用思路和利用可能。

總結:

  • 針對于discuz的ssrf漏洞,在補丁中限制了對內網ip的訪問,導致了很難被利用。
  • 在后臺getshell中,建議使用uc_center rce比較方便,并且通殺包括最新版本,后文有分析。
  • UC_KEY 直接getshell已在x3以上的最新版本被修復,但在一些老的3.2以前的版本可能被利用。

以上這些漏洞應該并不全面,且看似都比較雞肋,但往往千里之堤毀于蟻穴,幾個不起眼的小漏洞組合一下會發現威力巨大。仔細的讀者應該發現以上漏洞大部分能夠造成的最大危害是信息泄露,信息泄露有什么用呢?下面我們將接著分析Discuz的幾種密鑰,看到這兒你應該已經明白了,通過信息泄露,獲得相關密鑰,突破discuz的加密體系,進而獲取更高的權限。

Discuz的幾種密鑰分析

通過分析,在discuz中,主要有下面的幾種密鑰, 這些密鑰共同構成了discuz的加密解密體系,這里的命名有重復,我已經標記了對應key值以及key所在的位置。如下表所示:

主要探討的其實就只有 authkey,UC_KEY(dz),UC_KEY(uc_server),UC_MYKEY,authkey(uc_server) 5種,我們首先來看著幾個密鑰是怎么來的最后又到了哪兒去。

密鑰的產生

authkey,UC_KEY(dz),UC_KEY(uc_server),UC_MYKEY 都是在安裝的時候產生。authkey(uc_server)的產生是和UC_MYKEY息息相關的,在后文中詳細講述。生成代碼如下所示:

我們看見key的產生都依賴于discuz 自定義的random函數,出現過的authkey爆破問題也因此產生。在安裝時由于處于同一個cgi進程,導致mt_rand() 只播種了一次種子,所以產生了隨機數種子爆破和推測key的問題,在3.4版本中,authkey的產生已經是拼接了完整的32位字符串,導致了無法進行爆破推算出authkey的前半部,因此這個問題已經被修復,但這個漏洞原理值得學習。代碼最后可以看出authkey產生后還放入了數據庫中,最終authkey存在于數據庫pre_common_setting表和/config/config_global.php配置文件。 代碼中的 instal_uc_server()函數實現了UC_KEY(dz),UC_KEY(uc_server)的產生,使用了同一個生成函數_generate_key(),代碼如下:

產生的算法牽扯到安裝環境和安裝過程的http header信息,導致爆破基本失效,從而無法預測,最后UC_KEY(dz)保存到了/config/config_ucenter.php中,UC_KEY(uc_server)保存到了/uc_server/data/config.inc.php中。

Discuz Key的相關思考

我們通過查看源碼,去分析每個key影響的功能,通過這些功能點,我們可以去獲得更多的信息。信息的整合和利用往往是我們滲透的關鍵。下面我們將做一些拋磚引玉的思考并舉一些例子,但不會面面俱到一一分析,這樣也沒有意義,具體的代碼還是需要讀者自己親自去讀才能印象深刻。

1. authkey

authkey的使用在discuz主程序中占比很重,主要用戶數據的加密存儲和解密使用,比如alipay相關支付數據的存儲和使用、FTP密碼的存儲等等;還用于一些功能的校驗,比如驗證碼的校驗、上傳hash的校驗等等;用戶權限的校驗也用到了authkey,比如source/class/discuz/discuz_application.php_init_user() 利用authkey解碼了cookie中的auth字段,并利用解開的uid和pw進行權限校驗,但是光知道authkey并不能完成權限校驗,我們還需要知道用戶的”密碼hash“(數據庫pre_common_member表中的password字段,此處存儲的只是一個隨機值的md5,真正的用戶密碼hash在pre_ucenter_members中),當我們通過其他方法可以讀取數據庫數據時,我們就可以偽造登陸信息進行登陸,再比如source/include/misc/misc_emailcheck.php中authkey的參與了校驗hash的生成,當我們知道了authkey后,通過偽造hash,我們可以修改用戶的注冊郵箱,然后利用密碼找回來登陸前臺用戶(管理員不能使用密碼找回功能)。

2. UC_KEY(dz)

UC_KEY(dz)也是經常提到的UC_KEY GetWebShell的主角。它主要在2個地方被使用:一個是數據庫備份api/db/dbbak.php;一個是針對用戶以及登錄和緩存文件相關的操作,主要函數位于api/uc.php中的uc_note類。

關于UC_KEY(dz)的利用,網上基本都是通過uc.php來GetWebShell,但這個漏洞在新版本已經被修復了。UC_KEY(dz)的利用并不局限與此,你去閱讀dbbak.php代碼就會發現,有了UC_KEY(dz)我們可以直接備份數據庫,下載數據庫,從數據庫中找到相關信息進行進一步滲透。

另外一個地方就是uc_note類,比如里面的synlogin()函數可以偽造登陸任意前臺用戶。當然還有其他的函數,在這里就不一一分析。

3. UC_KEY(uc_server)

UC_KEY(uc_server)往往是被大家忽視的一個key,它其實比UC_KEY(dz)的使用更多。首先他同樣可以備份數據庫,對discuz代碼比較熟悉的同學應該知道dbbak.php這個文件有2個,一個是上面提到的api/db/dbbak.php;另外一個是uc_server/api/dbbak.php,他們的代碼可以說幾乎相同。唯一的區別是api/db/dbbak.php中多了2個常量的定義,基本沒有太大影響。這個2個文件都能被UC_KEY(dz)和UC_KEY(uc_server)操控。

UC_KEY(uc_server)幾乎管控了Ucenter的所有和權限認證相關的功能。例如權限驗證函數 sid_decode() ,在該函數中UC_KEY(uc_server)和用戶可控的http header共同產生了用于權限認證的sid,因此我們可以偽造sid繞過一些權限檢測。還有seccode的相關利用,在這里就不一一介紹。

整個discuz的程序其實是包含了discuz主程序和Ucenter,Ucenter更依賴于固定密鑰體系,個人感覺Ucenter的漏洞可能要比discuz主程序好挖些,你可以去試試。

4. UC_MYKEY

UC_MYKEY主要用來加密和解密UC_KEY(discuz),如下所示:

authkey(uc_server)存儲在數據庫的pre_ucenter_applications中的authkey字段,authkey(uc_server)生成的代碼如下:

現在我們就可以知道其實UC_KEY(dz)是可以從2個地方獲取到的,一個是配置文件,一個是數據庫。對discuz比較熟悉的同學這里會發現一個問題,通過注入獲得的authkey (uc_server),有時候可以直接當UC_KEY(dz)用,但有時候發現是一個大于64位的字符串或小于64位的字符串。這個是因為,如果你是默認discuz主程序和Ucenter安裝,這個時候數據庫pre_ucenter_applications中的authkey字段存儲的就是UC_KEY(dz),如果你通過ucenter后臺修改過UC_KEY(dz),數據庫pre_ucenter_applications中的authkey字段存儲的就是通過上面提到的算法計算出來的結果了,這個結果的長度是變化的,是一個大于等于40位的字符串。

總結

針對于getshell來說,在x3以前的低版本和部分未更新的x3.2以前版本,我們可以直接利用discuz的uc_key(dz)結合api/uc.php前臺getshell,獲得uc_key(dz)的方法有:

  1. 數據庫中的authkey(uc_server)結合UC_MYKEY,這個在UCenter后臺也能看見,沒有使用顯示。

  2. 文件泄露等問題獲得uc_key(dz)

在x3版本以后,對于key的利用主要集中在操作數據庫和UCenter功能上,利用各種辦法進入discuz后臺,結合接下來講到的后臺GetWebShell的方法獲取最終權限。

后臺GetWebShell的補丁繞過

在小于x3.4的版本中,網上已經公布的利用方法是:后臺修改Ucenter數據庫連接信息,由于寫入未轉義,一句話木馬直接寫入config/config_ucenter.php文件中,導致代碼執行。

但是在新版本的x3.4中已經修復了這個漏洞,代碼如下:

補丁對 $ucdbpassnew 進行了轉義,而且if(function_exists("mysql_connect") && ini_get("mysql.allow_local_infile")=="1" && constant("UC_DBHOST") != $settingnew['uc']['dbhost']), 該補丁還解決了惡意mysql文件讀取的問題。

繞過補丁

通過補丁,我們知道了所有的Ucenter配置參數都會進行轉義,但是我發現discuz的配置文件更改,都是利用字符替換完成的,在替換字符中,很容易出現問題,所以在源碼中尋找配置修改的相關代碼,最后在 api/uc.php 中找到了利用點。

在 updateapps 函數中完成了對 uc_api 的更新,這里的正則在匹配時是非貪婪的,這里就會存在一個問題,當uc_api為 define('UC_API', 'http://127.0.0.1/discuz34/uc_server\');phpinfo();//'); 時,我們執行updateapps函數來更新uc_api時就會將phpinfo();釋放出來。 要使用updateapps函數來更新uc_api,我們需要知道UC_KEY(dz)的值,而UC_KEY(dz)的值,恰好是我們后臺可以設置的。

利用分析

1.進入后臺站長-Ucenter設置,設置UC_KEY=隨意(一定要記住,后面要用), UC_API= http://127.0.0.1/discuz34/uc_server');phpinfo();//

成功寫進配置文件,這里單引號被轉移了,我們接下來使用UC_KEY(dz)去調用api/uc.php中的updateapps函數更新UC_API。

2.利用UC_KEY(dz) 生成code參數,使用過UC_KEY(dz) GetWebShell的同學肯定不陌生,這里使用的UC_KEY(dz)就是上面我們設置的。

3.將生成的數據帶入GET請求中的code 參數,發送數據包 !

4.訪問http://127.0.0.1/discuz34/config/config_ucenter.php 代碼執行成功

到此成功GetWebShell,在這個過程中,有一點需要注意的是,我們修改了程序原有的UC_KEY(dz),成功GetWebShell以后一定要修復,有2中方法:

  1. 從數據庫中讀取authkey(uc_server),通過UC_MYKEY解密獲得UC_KEY(dz),當然也有可能authkey(uc_server)就是UC_KEY(dz)。
  2. 直接進入Ucenter后臺修改UC_KEY,修改成我們GetWebShell過程中所設置的值。

0x03 XXE to 域控

在本節中我們會講到WEBDAV XXE(JAVA)利用NTLM Relay和一個機器賬戶去設置基于資源的約束委派來RCE的故事。當然繞過卡巴斯基dump lsass也是非常的精彩。流程圖示如下:

WEBDAV XXE

前文中已經提到了我們進入內網后發現一臺部署著java應用的web服務器,并探測出該網站存在/webdav目錄。

在一個國外安全研究員的ppt(What should a hacker know about WebDav? )中這樣提到: 一般webdav支持多種http方法,而PROPPATCH、PROPFIND、 LOCK等方法接受XML作為輸入時會形成xxe

我們探測下支持的http方法:

我們在測試PROPFIND方法時成功收到了xxe請求:

常規的xxe一般會想到任意文件讀取、以及網上提到的利用gopher打redis等。在《Ghidra 從 XXE 到 RCE》中提到利用java xxe做ntlm relay操作。由于sun.net. 發送HTTP請求遇到狀態碼為401的HTTP返回頭時,會判斷該頁面要求使用哪種認證方式,若攻擊者回復要求采用NTLM認證則會自動使用當前用戶憑據進行認證。

現在我們成功獲取到了NTLM認證請求,接下來就是NTLM中繼了。

NTLM中繼和域機器賬戶添加

什么是NTLM中繼

相信大家都不陌生,要理解什么是NTLM中繼首先要知道NTLM認證的大致流程,這里做個簡單講述,詳細請參考The NTLM Authentication Protocol and Security Support Provider。

NTLM身份驗證協議中包含3個步驟:

  1. 協商:NTLM身份驗證的第一步是協議的協商,以及客戶端支持哪些功能。在此階段,客戶端將身份驗證請求發送到服務器,其中包括客戶端接受的NTLM版本。
  2. 質詢:服務器以自己的消息作為響應,指示其接受的NTLM版本以及要使用的功能。該消息還包括challenge值。
  3. 響應:收到challenge后客戶端用hash將challenge加密,作為NTLM Response字段發送給服務器。

NTLM身份驗證是基于質詢響應的協議,服務器發送一個質詢,客戶端對這個質詢進行回復。如果質詢與服務器計算的質詢匹配,則接受身份驗證。

知道了NTLM身份認證的大致流程,我們再來說NTLM中繼,如下圖所示,如果我們可以讓Client A 向我們的Evil Server X,發起NTLM認證,那么我們就可以拿Client A的身份驗證信息去向Server B進行認證,這便是ntlm中繼。看到這里你會覺得說了那么多不就是中間人攻擊么,對就是中間人攻擊。

知道了NTLM中繼,結合Java WEBDAV XXE的作用,利用HTTP 401的認證,我們可以直接利用WEBDAV服務器的憑據向域控發起認證,讓域控以為我們是WEBDAV服務器。

在域中增加機器賬戶

在這里可能有同學有疑問了,前面不是提了中繼么?為什么不用《Ghidra 從 XXE 到 RCE》和《Ghost Potato》里提到的方式去Relay回自身調用RPC進行相關操作,還要增加機器賬戶呢?因為這個WEBDAV服務是system權限運行的,而system賬戶做Relay時是用機器賬戶去請求的,沒有辦法去調高權限RPC接口,所有這里不能直接Relay回自身調用RPC。

既然不能直接Relay回自身調用RPC,我們換一種思路,用基于資源約束委派一樣可以獲取權限

在通過基于資源約束委派進行利用時,需要有一個機器賬戶來配合(這里說法其實不太準確,應該是需要一個具有SPN的賬戶,更詳細的說是需要一個賬戶的TGT,而一個機器賬戶來代替前面的說法,是因為機器賬戶默認具有一些SPN,這些SPN包含了我們后面會用到的cifs等,這里就不細說了,不然又是一篇文章了,后面統一用機器賬戶來描述),而默認域控的ms-DS-MachineAccountQuota屬性設置允許所有域用戶向一個域添加多達10個計算機帳戶,就是說只要有一個域憑據就可以在域內任意添加機器賬戶。這個憑據可以是域內的用戶賬戶、服務賬戶、機器賬戶。

那么問題又來了,既然需要一個機器賬戶,前面提到的

system賬戶做Relay時是用機器賬戶去請求

這個地方說的機器賬戶,也就是我們文中的WEBDAV服務器的機器賬戶,為什么不用這個機器賬戶,要自己去增加一個呢?了解基于資源約束委派的同學應該知道,我們需要用機器賬戶去申請TGT票據,但是我們如果用WEBDAV服務器的機器賬戶,我們不知道這個機器賬戶的密碼或者hash。沒有辦法去申請TGT。如果是我們創建的機器賬戶,我們是知道密碼的,這樣才能去申請TGT了,這里就不在深入繼續分析了,里面涉及到的過程極其復雜,有興趣的同學可以自行學習。

回歸正題,我們怎么在域中去創建一個機器賬戶。

我們把在之前的discuz數據庫中的用戶名整理成字典,并通過kerberos AS_REQ返回包來判斷用戶名是否存在。

接下來將discuz的密碼拿到cmd5上批量解密,解密后發現大部分用戶的登錄密碼都是P@ssw0rd,于是使用密碼噴射(一個密碼和不同用戶名的組合去KDC枚舉) ,成功獲取到了一個域憑據n0thing@blueteam.com:P@ssw0rd

有了域憑據后就能連接域控ldap添加機器賬戶了,不得不說.net真是個好語言,用System.DirectoryServices.Protocols這個東西很輕松就能實現該功能。

有細心的同學看到這里可能會想: "用xxe中繼到域控的ldap然后添加一個機器賬戶不是美滋滋? 哪需要這么花里胡哨的!"。但是域控不允許在未加密的連接上創建計算機帳戶,這里關于加密涉及到tls/ssl和sasl,又是一堆的知識,這里就不細聊了。

用.net寫的小工具很輕松地添加上了一個機器賬戶。

現在我們有了機器賬戶,接下來就利用基于資源的約束委派。

基于資源的約束委派

Windows Server 2012中新加入了基于kerberos資源的約束委派(rbcd),與傳統的約束委派相比,它 不再需要域管理員對其進行配置,可以直接在機器賬戶上配置msDS-AllowedToActOnBehalfOfOtherIdentity屬性來設置基于資源的約束委派。此屬性的作用是控制哪些用戶可以模擬成域內任意用戶,然后向該計算機(dev2)進行身份驗證。簡而言之:如果我們可以修改該屬性那么我們就能拿到一張域管理員的票據,但該票據只對這臺機器(dev2)生效,然后拿這張票據去對這臺機器(dev2)進行認證(這里只是簡單描述,可能不太準確,還是那句話基于資源的約束委派整個過程細節及其復雜,筆者也不敢說掌握全部細節)。

現在我們開始實際操作,首先在我們的VPS上利用impacket工具包中的ntlmrelayx.py工具監聽。

然后用xxe請求我們的VPS,接著將憑據中繼到域控服務器的LDAP服務上設置基于資源約束委派。

再用s4u協議申請高權限票據。

獲得票據以后就可以直接登錄WEBDAV服務器了

整個RCE過程到此結束了,但是還沒有拿下域控,滲透任務還沒有結束,先上一個GIF演示整個RCE過程,接下來再講怎么拿下域控。

卡巴斯基的對抗

其實拿下域控的過程很常規,就是在WEBDAV服務器上抓到了域管理員的賬戶密碼。但是這里難點是卡巴斯基的對抗,繞不過你就拿不到域管理員的賬戶密碼。

這里安裝的卡巴斯基全方位防護版來進行測試。

1. 繞過卡巴斯基橫向移動

在真實場景中并不會像本地環境一樣順利,當我們拿到一張高權限票據后準備對dev2機器進行pass the ticket時存在卡巴斯基怎么辦呢?常規的smbexec.py會被攔截的。

我們這里的繞過方法是用smb上傳一個beacon再通過創建啟動服務執行beacon全程無攔截,當然beacon.exe需要進行免殺處理。

2. 繞過卡巴斯基抓lsass中的密碼

我想最糟心的事情莫過于知道域管理員登錄過這臺機器,但卻沒有辦法抓密碼。下面將介紹如何解決這個問題。相信在紅隊行動中遇到卡巴斯基的小伙伴不少,也知道他對防止從lsass中抓取密碼做的是多么的變態。即使你使用微軟簽名的內存dump工具也會被攔截,更不用說什么mimikatz了。

偶然在國外大佬博客上看到了一篇通過RPC調用添加一個SSP dll的文章Exploring Mimikatz - Part 2 - SSP,突然醍醐灌頂,lsass自身絕對可以讀自己內存呀,加載dll到lsass進程然后dump內存不是就可以繞過了?不禁感嘆:站在巨人肩膀上看到的世界果然更為遼闊。

下載編譯這個代碼ssp_dll.c 然后再寫一個dump 進程內存的dll。

這樣就繞過了卡巴斯基dump到了lsass的內存了。

最后本地導入mimikatz的常規操作就不細說了,上幾個截圖。

到此是真的要結束了,有域管理員的賬戶密碼,怎么拿下域控,我相信這個不用多說了。

0x04 總結

我們回顧一下,從discuz到xxe,從xxe到域控,整個過程我們在真實的滲透過程中其實沒有花費太多時間,可能得益于平時的積累。針對此次滲透,我們還是收獲滿滿,希望你也是。

最后的最后,我們來進行一次反思。

Discuz并不是無懈可擊的,不要聞風喪膽,遇見就上不要慫,可能他就是你的突破口。


Paper 本文由 Seebug Paper 發布,如需轉載請注明來源。本文地址:http://www.bjnorthway.com/1144/