作者:n1nty@360 A-Team

此次 CVE 所涉及到的背景知識與我之前看過的一些協議資料重合度很高,所以在這裡嘗試對此 CVE 進行一下初步的解讀,有錯誤的話還請各位指出。看的時候最好配合原文一起看,原文中有一些圖片會助於理解。

blog.preempt.com/how-we

糾錯

首先,標題的描述並不是太準確。不準確在於:

  1. 漏洞存在於 CredSSP 中,並不是直接存在於 MS-RDP。MS-RDP 只不過利用到了 CredSSP 進行了身份驗證(只有在開啟 NLA 的時候)。所以理論上只要是用到了 CredSSP 的協議都會有這個問題。
  2. 這並不是一個直接的 RCE 漏洞。

本次 CVE 的本質

從目前的作者原文披露的信息來看,這是一次突破了 SSPI 簽名與加密的 Kerberos Relay。利用中間人技術,將 MS-RDP 中用到的 CredSSP 驗證數據包 Relay 至了遠程的 RPC 介面用於達到類似橫向移動的效果(基本所有的橫向移動全是依賴的 RPC),並且突破了數據包簽名與加密。作者目前只實現了 Kerberos Relay,並沒有實現 NTLM Relay,且目前只實現了 Relay 至 RPC 服務。

需要知道的背景知識簡述

  1. CredSSP
  2. Kerberos
  3. Credential Relay 攻擊的原理

CredSSP

這是 Windows 內置的一種身份驗證實現,它實現了 SSPI。它並不是一個全新的身份驗證協議,它只是 Negotiate SSP 的一個包裝器。CredSSP 的出現主要是為瞭解決 A-TEAM 之前在另一篇公眾號文章 老牌工具 PsExec 一個瑣碎的細節 中提到的 「authentication double hop」 的問題。不明白 authentication double hop 是什麼的朋友可以看一下我那篇文章 。

CredSSP 只是 Negotiate SSP 的一個包裝器,工作流程大概如下:

  1. 建立 TLS 會話
  2. 利用 Negotiate SSP 與遠端進行身份驗證。Negotiate SSP 則將選擇性地利用 Kerberos SSP 或 NTLM SSP 與遠端進行身份驗證。Negotiate SSP 生成的 auth token 將會被 CredSSP client 封裝在 TSRequest 消息中發送至 CredSSP server,同樣 CredSSP server 端所依賴的 Negotiate SSP 所生成的回復 auth token 也將會封裝在 TSRequest 被返回至客戶端。這個過程也許會往返多次
  3. 身份驗證通過後,通過 TSCredential 將客戶端的原始憑據發送至遠端伺服器。以解決遠端伺服器 double hop 的問題。

問題出現在上面提到的第 2 步,所以這裡再細化一下第 2 步。下面是一張更詳細的 CredSSP 流程圖:

第 1 步至第 4 步是建立 TLS 會話鏈接的過程。第 5 第 6 步是 CredSSP 使用下層的 Negotiate SSP 進行身份驗證的過程。這兩步有可能會反覆多次被執行。

在第 5 步和第 6 步執行完後,下層的 Negotiate SSP 已經完成了身份驗證,且已經得了用於進行 SSPI 簽名與加密的 session key。

第 7 步,CredSSP client 利用 session key 對服務端的證書(CredSSP 是基於 TLS 會話的) public key structure 進行了 SSPI 加密,將結果發送至 CredSSP server 進行驗證。

第 8 步,CredSSP server 利用 session key 對自身證書的 public key structure 進行 SSPI 加密,將結果發送至 CredSSP client 進行驗證。

這兩步的本意是為了防止 Credential Relay 一類的攻擊(我的理解是這種方式依然只能防止攻擊者偽裝成一個惡意的 CredSSP Server 來將 CredSSP client 的驗證信息 relay 至另一個 CredSSP server。而無法防止將 CredSSP client 的驗證信息 relay 至使用其他 SSP 且沒有啟用 SSPI 加密簽名功能的其他協議 比如 SMB。),像 A-TEAM 之前在另一篇公眾號文章 360 A-TEAM 帶你走進 NTLM-Relay 中提到的那樣,在驗證階段就引入了 session key。

問題出現在第 7 步。

第 7 步

第 7 步的時候,CredSSP client 將 CredSSP server 端的 public key structure 進行了 SSPI 加密與簽名,並發回了 CredSSP server。

原作者很機智地想到,如果 CredSSP server 的 public key 是我們自己可控的呢?有沒有可能有這麼一段數據,它既是一個有效的 RSA public key,又是其他可利用協議的一段有效數據?原作者最終解決了這個問題,而且他找到了一個可利用的協議:RPC,並利用 RPC 的遠程計劃任務介面實現了 RCE。

因為 POC 還沒有公佈,所以以下步驟只是我的猜測:

  1. 攻擊者站在中間人的位置,偽裝成一個 CredSSP server
  2. 受害人利用 RDP 連接遠端機器利用 CredSSP 進行驗證,實際上連接到的是攻擊者偽裝的 CredSSP server
  3. 因為 CredSSP 基於 TLS,所以攻擊者給客戶端返回一個自己的證書(要注意的是,CredSSP client 本身是不會對 CredSSP server 的證書進行 CA 檢查的),用於解密 CredSSP client 發往自身的加密驗證流量。
  4. 根據上面那張圖,CredSSP 的第 5 與第 6 步是雙方進行認證數據包的交換(auth token)。一旦攻擊者發現 CredSSP client 開始利用 TSRequest 與自己來進行身份認證,攻擊者則開始將這些認證數據包 Relay 至目標的 RPC 服務。當 CredSSP Client 認證完成後,攻擊者與遠程的 RPC 服務也已經完成了認證。
  5. 感覺一直到上一步,看起來都只是一個正常的 Credential relay 的過程,並沒有什麼新的東西。原作者的機智才剛剛展現。
  6. 攻擊者與遠程 RPC 服務進行了身份驗證後,是無法進行 RPC 調用的。因為 RPC 對後面的數據包有簽名與加密的檢查。攻擊者無法得知用於簽名與加密的 session key。
  7. 回到上面那張圖的第 7 步,CredSSP client 會利用 session key 將服務端發來的 public key structure 進行加密然後發送至 CredSSP Server。這個時候,如果我們之前給客戶端返回的 TLS 證書中的 public key 正好就是用於進行 RPC 調用的那個數據包呢?核心就在這裡。client 會幫我們對這個數據包進行加密與簽名,所以攻擊者在無需知道 session key 的情況下,繞過了加密與簽名進行了遠程 RPC 調用。因為 CredSSP client 只會對 public key structure 進行一次加密與簽名,所以要求被我們利用的那個協議只需要發送一個加密的數據包就可以完成敏感操作,而 RPC 符合這個要求。

為了更清晰地理解上面的步驟,這裡借用原文的一張圖:

原作者解決了一些其他的問題:

  1. 為瞭解決 public key 是一個有效的 RSA public key 的同時,又是一段有效的 RPC 數據,進行了那段我看不懂的數學。:(
  2. CredSSP client 並不是單純對 public key 進行加密,而是對 public key structure 進行加密。public key structure 是對 public key 進行 DER 編碼後的結構。因為 DER 是 TLV 格式的編碼,編碼後會在原始數據前加上表示 type 與 length 的位元組,所以客戶端最終加密的那段 public key structure 的前幾個位元組是不可控的代表 type 與 length 的位元組,後面纔是我們的 public key。作者通過調用那些第一個參數是字元串或指針的 RPC 方法來解決了這些不可控的位元組帶來的問題。

3.為什麼 NTLM 無法使用,只能使用 Kerberos

原文中作者提到,如果想 Relay 至 RPC 協議,則用於認證的協議只能是 Kerberos,不能是 NTLM。(當然這是跟 RPC 協議自身有關的,如果你能找到其他可利用的協議的話,也許就沒有這個問題。)原文中給出了一張圖,用於解釋這個問題:

RPC 如果使用 NTLM 進行了身份驗證,則要求後續的方法調用數據包的 RPC Application Data 部分是加密的,再將 DCE Header 與 加密後的 RPC Application Data 進行簽名。CredSSP 第 7 步是直接對整個數據包進行加密與簽名,所以不符合這個要求。所以在 RPC 的場景下,不能進行 NTLM Relay,只能進行 Kerberos Relay。

Kerberos 與 SPN

原文中作者目前只實現劫持 RDP 中的 CredSSP 並 Kerberos Relay 至 RPC。這一點說明瞭,只能 Relay 至與原始服務(RDP)是同一個啟動賬號的其他服務。因為:

  1. 受害者通過 RDP 連接嘗試連接 Server1, CredSSP 將使用 Kerberos 與 Server1 進行認證,
  2. 攻擊者劫持了這個連接,嘗試將 Kerberos 認證 Relay 至 Server2
  3. 因為受害者傳遞過來的 ticket 是由 Server1 的機器賬號密碼加密(因為 RDP 是由 Server1 的 SYSTEM 啟動)的,所以攻擊者只能將這個 ticket relay 至由 Server1 的 SYSTEM 許可權啟動的其他服務。如果是 relay 至非 Server1 SYSTEM 啟動的服務,則這個 ticket 將無法被目標服務解密,認證將會失敗 。

那麼另一個問題就是,受害者原本是想訪問 Server1 的 RDP 服務,所以受害者從 KDC 處申請到的 service ticket 中的 sname 應該是 RDP/SERVER1 之類的。為什麼這張票可以被用於訪問 RPC 服務呢(很明顯 RPC 服務的 SPN 不可能與 RDP 服務的 SPN 相同)。關於這個問題,可以參考一下下面這篇由 impakcet 作者寫的文章:

coresecurity.com/blog/k

一句話就是:ticket 中的 SPN 是什麼並不重要,你可以將 RDP/SERVER1 改成 XXX/SERVER1,只要目標伺服器上的 RDP 與 XXX 服務的啟動賬號是同一個。

文章轉載自360 A-TEAM

(360 A-TEAM 長期招收高級安全研究人員,APT 攻防人員,請聯繫 [email protected]

本文轉載自:360 A-TEAM

如若轉載,請註明出處:mp.weixin.qq.com/s/7tKZ安全客 - 有思想的安全新媒體

安全客徵稿啦啦啦啦~乾貨技術文章儘管投過來,獎勵豐厚

詳情請戳→anquanke.com/contribute


推薦閱讀:
相關文章