上回我們說到,通過ruler可以給已知使用者名、密碼的使用者增加規則,進而在使用Outlook連接配接Exchange郵箱伺服器的主機上做到任意代碼執行。那麼問題來了,如果不知道該使用者的密碼,能否控制他們的主機呢?
資料包分析
首先需要明白ruler的具體實作過程和原理,到底是如何給其他使用者增加規則、修改首頁、發送form的。但是大緻上我們可以猜測是給Exchange伺服器對應的接口發送了幾個資料包做到的。
這些資料包發送到了哪個接口,需要從接口處獲得什麼作為傳回,以便進行下一次的請求。
是以需要對ruler的源碼進行閱讀同時結合對它發資料包的分析弄清楚整個的流程。
采用Fiddler對ruler的資料包進行解密(試過BurpSuite,但是它對NTLM認證的支援不好,會造成認證失敗)
在Fiddler中進行如下操作,最後勾選
Decrypt HTTPS traffic
就能夠對發送的流量進行解密。
Tools
Options
HTTPS
Capture HTTPS CONNECTs
Decrypt HTTPS traffic
ruler自帶了proxy選項,隻需設定proxy為Fiddler監聽的8888端口就能成功抓取到對應流量
--proxy value If you need to use an upstream proxy. Works with https://user:pass@ip:port or https://ip:port
複制
當通過ruler指令
homepage display
檢視某使用者的收件箱首頁時,收發資料包的具體動作如下,共有6個資料包,并且認證的方式是
HTTP Basic
身份認證。當使用者通路受限資源時,伺服器會傳回401狀态碼要求進行身份認證,身份認證成功之後會進行6個請求,首先請求了
autodiscover/autodiscover.xml
頁面,接着在擷取了對應郵箱的
MailboxId
之後向對應的mapi接口發送了mapi請求,獲得請求結果。
![](https://img.laitimes.com/img/__Qf2AjLwojIjJCLyojI0JCLiAjM2EzLcd3LcJzLcJzdllmVldWYtl2PnVGcq5id2YWdlJDMkh3YvwVO0QDO2ITMtUGall3LcVmdhNXLwRHdo9CXt92YucWbpRWdvx2Yx5yazF2Lc9CX6MHc0RHaiojIsJye.jpeg)
CVE-2018-8581
一個非常經典的漏洞,網上分析該漏洞的文章也較多。通過該漏洞能允許任意使用者僞裝成Exchange伺服器上的其他任何人。通過向SOAP請求向Exchange伺服器發送請求能讓Exchange伺服器向制定的IP位址發送NTLM hash,該hash值可以被我們用來重新與Exchange伺服器進行互動,并且該hash值是在
NT\AuthoritySytem
上運作的 ,權限很大。
這說白了就是一種中間人攻擊,使用管理者權限的令牌去對其他的使用者賬戶進行相應的設定了。
最初的攻擊方式其一是通過NTLM中繼讀到登入域控的任意使用者的NTLMhash,這樣就能夠登入到該使用者主機執行任意指令。
python wmiexec.py -hash LMhash:NThash username@ipaddress
python wmiexec.py -hashes :NThash username@ipaddress
複制
其二是通過NTLM中繼以Exchange Server的權限向Exchange Server發送SOAP請求,将某一使用者的收件箱委托到目前已經擷取使用者名及密碼的賬戶上。這樣就能以目前已經擷取使用者名及密碼的賬戶讀取其他使用者的郵件了。網上大多數的攻擊腳本都采用的上面提到的兩種攻擊方法。
另辟蹊徑
很多的漏洞随着時間會漸漸淡出人們的生活,這個周期通常需要一兩年,當廠商提出某種新的漏洞利用緩解方式之後,有些漏洞便無法再使用了。如何抓住廠商完善産品“空窗期”,利用漏洞或者某種特性,做更多的事情,是滲透測試人員在每一次紅隊行動中需要思考的問題。
下載下傳其他使用者的郵件
通過高權限的使用者token以及SOAP請求,也能夠下載下傳其他使用者的郵件。SOAP請求的内容需參考微軟的文檔。
最後做到的效果就是通過python編寫的腳本中繼pubsubscription的請求,繼而修改其他使用者收件箱檔案夾的權限為
Editor
。修改檔案夾權限的關鍵在于
通過已經擷取的賬戶使用者名及密碼登入,能夠讀取其他使用者收件箱中的郵件。讀取郵件的代碼需要用
C#
進行編寫,使用
EWS Managed API
開發
https://docs.microsoft.com/en-us/exchange/client-developer/exchange-web-services/get-started-with-ews-client-applications#create-your-first-ews-application
給其他使用者添加Rule規則
通過之前的抓包我們發現ruler與exchange進行互動的方式仍然是HTTP Basic Auth的方法。這樣利用
CVE-2018-8581
的漏洞就能以管理者的權限成功通過認證。希望能夠結合中繼的請求認證方式,給其他的使用者增加rule規則。因為ruler的作者自己實作了一套MAPI的規則,代碼全部由golang編寫,并且代碼量很大。權衡了一下工作量,還是用go語言重寫relayNTLM更容易一些,通過NTLM認證之後給其他使用者添加規則。
首先要弄清楚的是這6個請求之間的邏輯關系,即在發送後一個請求之前需要從前一個請求當中擷取什麼資訊。
執行ruler并加上
--verbose
參數
$ ./ruler --nocache --insecure --verbose --username user3 --email [email protected] homepage display
Password:
[+] Retrieving MAPI/HTTP info
[*] Autodiscover step 2 - URL: https://internet.local/autodiscover/autodiscover.xml
[*] MAPI URL found: https://exchange2016.internet.local/mapi/emsmdb/[email protected]
[*] MAPI AddressBook URL found:
[*] User DN: /o=First Organization/ou=Exchange Administrative Group (FYDIBOHF23SPDLT)/cn=Recipients/cn=4a22881a84c9483794236d11d38e9098-user3
[*] Got Context, Doing ROPLogin
[*] And we are authenticated
[*] Openning the Inbox
[+] Getting existing endpoint
[+] No endpoint set
[*] And disconnecting from server
複制
除了擷取
MailboxId
的請求之外一共有五個請求
1.最開始的請求是擷取Context
2.第二個請求是做ROPLogin
3.第三個請求是打開Inbox
4.第四個請求是獲得(設定)Rules
5.最後一個請求是關閉連接配接
前兩個請求是發送使用者名密碼與Exchange進行連接配接,關鍵的函數有這樣幾個,最開始的包發送到
autodiscover/autodiscover.xml
進行認證,擷取userDN。擷取了userDN之後才能進行認證登入。
connect
getMapiHTTP
MAPIDiscvoer
autodiscover
get userDN, userDN是用來認證登入的
調用
mapi.Authenticate
與Exchange進行登入互動認證,這個過程發送了兩個資料包,分别在
sendMapiConnectRequestHTTP
函數以及
AuthenticateFetchMailbox
當中實作。
mapi.Authenticate
AuthenticateHTTP
sendMapiConnectRequestHTTP
AuthenticateFetchMailbox
調用
mapi.getFolder
擷取Exchange伺服器上目前賬戶的檔案夾資訊,通常不同的檔案夾有不同的FolderID,這個過程中發送了一個資料包。
mapi.getFolder
GetFolder
GetFolderFromID
接下來根據要實作的功能進行調用研究,對于getrules的功能,構造好getrules的請求,這個過程隻發送了一個資料包。
displayRules
printRules
mapi.FetchRules
發送資料包斷開連接配接,經過實驗,這個資料包最後也可以舍棄掉,斷不斷開無所謂,入了就是入了。
mapi.Disconnect
長連接配接的模拟
在修改程式攻擊腳本的過程中遇到了長連接配接的問題,因為HTTP Basic認證需要在同一個TCP連接配接中發送和接受資料,是以兩次請求的過程中必須保證使用的是同一個TCP連接配接。用python進行長連接配接請求用的是
http.client
包當中的
HTTPSConnection
和
HTTPConnection
類。通過這兩個類生成長連接配接發送POST和GET請求。
在golang當中需要類似的方法保持連接配接并發送POST和GET資料包,搜尋了一段時間發現調用
http.Client
類當中的
Do
方法能夠發送請求。并且如果将
Client
類變成全局變量就能實作每次發送資料都通過同一個TCP連接配接。
var tr *http.Transport
var client *http.Client
複制
Cookie設定
go語言當中也能對Cookie進行設定,它也用一個
http.Client
類,初始化的時候提供一個
cookiejar
變量作為參數,長連接配接中會自動根據傳回頭中的
Set-Cookie
值設定
cookiejar
中的
Cookie
并在下一次請求中攜帶
Cookie
。
tr = &http.Transport{
TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
}
jar, _ := cookiejar.New(nil)
client = &http.Client{Transport: tr, Jar: jar}
複制
是否有辦法通過Cookie的設定減少需要中繼的請求數量?在測試的過程中列印出
cookiejar
中的鍵值對,檢視每次請求過程中發送到伺服器上的cookie值。
u, _ := url.Parse(MAPI_URL)
for _, cookie := range client.Jar.Cookies(u){
fmt.Printf("%v = %v\n", cookie.Name, cookie.Value)
}
複制
經過實驗發現每次請求和傳回會加上一個
MapiSequence
的Cookie,
-
前面的數字表示請求的資料包順序值,
-
後面的内容是随機生成的4個位元組進行編碼後的結果,這個内容不是和使用者帳号綁定的,每次生成的位元組内容都不一樣。前面的數字表示整個Mapi請求進行到了第幾階段,一整套的Mapi請求共有5次,這個數字會從0增長到4。
MapiSequence = 1-VQjiZg==
複制
減少或者跳過其中的步驟會導緻認證失敗,增加rule規則的話必須得完成前4次互動(最後一次互動斷開連接配接可以不要)。但在有了Cookie的值之後,隻要在用戶端設定好了Cookie就不用在請求的過程中帶上
Authorization
,也就是說不用中繼5次NTLM認證了。一次中繼之後獲得cookie,就能夠用這次獲得的cookie進行下面的4次請求。
修改其他使用者的HomePage
接收到的請求包含了UserAgent,不包含Cookie。UserAgent當中有使用的Outlook版本以及.NET版本、Windows版本、解析html的ie庫版本。其中Trident标簽在IE8之後都存在,并且是使用的IE浏覽器版本号減4。
$ ncat -lvv -p 8000
Ncat: Version 7.80 ( https://nmap.org/ncat )
[...]
GET / HTTP/1.1
Accept: */*
Accept-Language: zh-Hans-CN,zh-Hans;q=0.5
Accept-Encoding: gzip, deflate
User-Agent: Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 10.0; WOW64; Trident/7.0; .NET4.0C; .NET4.0E; Microsoft Outlook 16.0.4266)
Host: 192.168.110.100:8000
Connection: Keep-Alive
複制
也就是說修改了使用者HomePage之後可以獲得對方使用的
Outlook
軟體版本資訊。修改homepage後在首頁代碼插入漏洞利用代碼,通過IE中存在的漏洞擷取使用者權限。
攻擊效果展示
攻擊的過程是通過python腳本讓Exchange伺服器發送push_subscription請求,同時用golang腳本在本機啟動中繼伺服器,監聽端口獲得HTTP請求的headers,中繼伺服器會将請求重新轉發到Exchange伺服器上,實作任意賬戶規則的添加。
https://www.bilibili.com/video/BV1kT4y1E7Jj
如果需要中繼添加規則的go語言代碼可以私信我。
防禦辦法
将Office更新到最新版本
檔案
Office賬戶
Office更新
更新了之後删除了執行應用程式以及腳本的功能,同時在form表單中無法執行相應的“宏”代碼了。
*本文作者:Kriston,轉載請注明來自FreeBuf.COM