原文鏈接:Phan tích CVE-2023-29357 – Microsoft SharePoint ValidateTokenIssuer Authentication Bypass Vulnerability
譯者:知道創宇404實驗室翻譯組

CVE 簡要說明

CVE-2023-29357它允許攻擊者繞過身份驗證并升級權限,是一個影響SharePoint使用的漏洞。由于未正確驗證 JWT 令牌的簽名,該漏洞存在于 ValidateTokenIssuer 方法內部。

受影響的版本為:小于16.0.10399.20005。

相關公告:

解決辦法

  • 升級到最新版本的SharePoint。
  • 啟用AMSI集成功能并使用Windows Defender。

具體分析

SPJsonWebSecurityBaseTokenHandler類中添加MissingAlgorithm枚舉,以覆蓋傳入的令牌缺少算法的情況。

img

重寫ReadToken方法,并調用SPAuthenticationAlgorithmValidator.ValidateAlgorithm

img

ValidateAlgorithm繼續調用HasValidAlgorithm方法來檢查JWT中的alg的值。

img

ZDI的公告中也描述了該漏洞存在于ValidateTokenIssuer方法中。補丁代碼添加了調用SPClaimsUtility.IsEnableOldHashedProofTokenFormat方法的代碼段。

img

img

調用堆棧到ValidateTokenIssuer

img

基于以上信息,可以用該算法制作 JWT 令牌并執行與 JWT 發行者( JWT 令牌 none 值)相關的操作。

為了進行身份驗證,SharePoint會從以下兩個位置獲取令牌: GET param prooftoken/headerX-PROOF_TOKEN和 header Authorization。

img

該令牌需要具有以下值:

img

  • ver: giá tr? ph?i là hashedprooftoken.

  • nbfexp: JWT 令牌的當前時間值和過期時間

  • audiss: 是目標受眾和發行者的值,這里必須是00000003-0000-0ff1-ce00-000000000000。該值00000003-0000-0ff1-ce00-000000000000代表Office 365 SharePoint Online的應用程序ID,其也可以在本地部署的SharePoint版本中使用。

img

圖片來源:https://learn.microsoft.com/en-us/troubleshoot/azure/active-directory/verify-first-party-apps-sign-in#application-ids-of-commonly-used-microsoft-applications

  • realm: 這個值通過向API發送Authorization中的令牌值的請求,其會泄露該值。

img

在嘗試使用上述格式發送JWT后,SharePoint識別出當前用戶是“SharePoint App”。

img

img

雖然用戶已經成功認證SharePoint App,但該漏洞的目的是我們需要冒充farmadmin賬戶。使用/_api/web/siteusers端點列出當前站點上具有權限的用戶。

img

為了模擬其他賬戶,我們需要修改proof token中的nameid字段.此時,我們的proof token如下所示:

img

在使用新令牌進行請求后,進程報錯Specified method is not supported

img

進行調試找出原因,異常在SPApplicationPrincipalName.CreateFromString方法中顯現。

img

主要原因是我們當前的值applicationPrincipleName沒有@字符,因此無法拆分成長度為2的數組。

img

根據堆棧跟蹤定位到SPApplicationPrincipalName.CreateFromString方法

從堆棧跟蹤向上追溯一點,SharePoint會檢查SPAppRequestContext.Current是否有效,如果有效,則調用SPAppRequestContext.Current.ClientId ? SPApplicationPrincipalName.CreateFromString,如上面的堆棧跟蹤截圖所示。

img

因此,只需要將SPAppRequestContext.Current的值設置為null,就不會再調用ClientId了。

經過一段時間的調試,我發現SPAppRequestContext.InitCurrent方法負責給SPAppRequestContext.Current賦值。其中調用了SPApplicationRequestHelper.IsApplicationRequest方法來檢查發送的請求是否是“應用程序請求”。

img

該方法如下:

img

在這里,我們只需要關注spincomingOAuthIdentityType兩個常量SPIncomingOAuthIdentityType.UserAndApplicationSPIncomingOAuthIdentityType.ApplicationOnly進行比較。只要我們的請求不符合這兩個條件,SPAppRequestContext.Current就是null

為了使spincomingOAuthIdentityType不等于上述兩個值,我們需要關注SPIncomingTokenContext.SetIdentityType方法。該方法通過我們發送的proof token來確定我們的token是用戶還是應用程序。

img

經過一段時間的調試,我們發現當我的proof token中的isuser字段的值為true時,可以將claimsIdentity.Actor的值設置為null,從而不進入if語句的內部代碼塊。

img

然后,程序繼續執行到下面的SPIncomingTokenContext.IsProofToken方法,該方法檢查proof token中的tt字段,如果該字段不存在,則跳過并返回false

img

因此,我們成功將IdentityType設置為UserOnly而不是UserAndApplicationApplicationOnly

img

此時,SPApplicationRequestHelper.IsApplicationRequest的返回值為false,app請求上下文設置為null

img

img

至此認證已經成功。

img

目前的proof token是:

img

在使用新的令牌重新嘗試后,結果如下:

img

成功模擬farmadmin賬戶后,我們可以繼續利用CVE-2023-24955來RCE,這個漏洞我會在下一篇博文中寫到。


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