Invisible password sprays. Invisible logins. Full tokens returned.

我是 Nyxgeek。現在是 2026 年,我還有兩個 Azure Entra ID 登入記錄繞過漏洞要與各位分享。別太興奮… 這些繞過漏洞最近已被修復,但我認為讓大家知道這件事很重要。

透過向 Azure 驗證端點發送一個特別構造的登入嘗試,有可能在活動未出現在 Entra ID 登入記錄中的情況下,擷取有效的權杖。這是關鍵的記錄… 全世界管理員都依賴這些記錄來偵測入侵… 而這些記錄卻可以被設為可選。

今天我將帶大家了解我在過去三年中發現的第三個和第四個 Azure 登入記錄繞過漏洞。我還將探討如何使用 KQL 查詢來偵測登入記錄繞過。透過了解 Microsoft 過去的錯誤,我們可以試圖為他們未來的失敗做好準備。

自 2023 年以來,我已經發現了四個 Azure Entra ID 登入記錄繞過漏洞。這意味著我找到了四種完全不同的方法,可以在不顯示在 Azure Entra ID 登入記錄中的情況下驗證 Azure 帳戶的密碼。雖然前兩個僅能在不產生記錄的情況下確認密碼是否有效,但我最新的記錄繞過漏洞卻能返回功能齊全的權杖。

先前,我曾撰寫過關於 GraphNinja 和 GraphGhost 的文章 — 這兩個記錄繞過漏洞允許使用者在不產生任何「成功」登入記錄事件的情況下識別有效密碼。兩者都不算太複雜。您可以在這裡和這裡找到詳細描述這些漏洞的部落格文章。

透過指定外部租戶 ID 作為端點,在不建立記錄的情況下驗證密碼

透過提供特定登入參數的無效值,導致整體驗證流程在執行憑證驗證後失敗,從而繞過成功登入事件的記錄

快速說明一下 — 名稱澄清:雖然我使用了 Graph- 前綴來標識這些不同的繞過漏洞,但或許使用 Entra- 前綴會更恰當,因為它們不僅限於 Graph 登入。

在這些情況下,被繞過的記錄是 Azure Entra ID 登入記錄。登入方法是透過 HTTP POST 到 Entra ID 權杖端點 login.microsoftonline.com,使用 OAuth2 ROPC 流程,並將 Graph API 作為我們預期的資源/範圍。我們提交使用者名稱和密碼、應用程式 ID 以及目標資源/範圍,然後就會收到 Graph API 的持有者權杖或重新整理權杖。

下方可以看到執行「正常」驗證的範例 curl 命令:

當提供有效的用戶名和密碼時,將返回一個可用於存取 Graph API 的權杖。

在 GraphNinja 繞過漏洞中,只需將驗證嘗試指向另一個租戶(例如:https://login.microsoftonline.com/00000000-1234-1234-1234-000000000000/oauth2/v2.0/token)。任何其他有效的租戶 GUID 都可以,只要不是受害者的租戶即可。驗證回應仍會指示是否找到有效密碼,但由於該登入是針對使用者不存在的外部租戶執行的,因此登入會失敗。由於驗證是針對外部租戶,因此在實際使用者的父租戶中不會產生失敗或成功的驗證記錄。外部租戶也不會產生記錄,因為只有該租戶內有效使用者的記錄才會產生,而目標使用者並不存在於外部租戶中。雖然 GraphNinja 沒有返回權杖,但它會向攻擊者指示密碼是否有效,而管理員卻不會收到任何通知。Microsoft 已透過新增記錄來補救此疏忽。

在 GraphGhost 繞過漏洞中,提供無效的 Client ID 值會導致整體驗證流程失敗,但是在憑證驗證發生之後。透過提供無效的 Client ID 值,將會導致密碼驗證後步驟失敗,整體驗證流程將會失敗,並且管理員會將此視為失敗的登入,記錄中不會顯示密碼已被成功猜測。與 GraphNinja 類似,沒有返回權杖,但密碼已驗證而管理員卻沒有收到任何通知。Microsoft 已透過在登入記錄中新增詳細資訊來指示密碼是否成功,從而修復了此問題。

現在您已經了解了 2023 年和 2024 年的發現,讓我們來看看 2025 年的發現。

讓我們從我稱之為 GraphGoblin 的開始。我在測試 Microsoft 驗證 POST 的參數時偶然發現了這個繞過漏洞。測試範圍(scope)參數時,我首先嘗試了一些簡單的操作,例如提供無效的範圍值。然而,我發現如果範圍值不是有效的範圍名稱,或者不符合預期的格式,該範圍就會被拒絕。

AADSTS70011: 提供的請求必須包含一個 'scope' 輸入參數。輸入參數 'scope' 的提供值無效。範圍 [scope] 無效。範圍格式無效。範圍必須是有效的 URI 形式 <https://example/scope> 或有效的 GUID <guid/scope>。

這個錯誤訊息並不完全誠實。您也可以指定特定的範圍,例如 openid 或 Directory.Read.All。如果使用 URL 或 GUID 格式,它將驗證目標資源,然後是範圍。這種對範圍值的驗證阻止了任意長字串的評估。

或者,它阻止了嗎?如果我們提交的字串是有效的,但重複呢?例如,與其指定 openid 作為範圍值,不如提交一堆相同的字串,例如 openid openid openid?

它通過了!但它繞過了記錄嗎?我設定了 15 分鐘的鬧鐘,回來檢查 Azure Entra ID 登入記錄,發現沒有新的登入!太棒了!我再等了 15 分鐘才真正慶祝。然後我用朋友的租戶測試了一下,以確保萬無一失。這是一個穩固的繞過。

為了展示這個有多麼簡單,下面是使用 curl 和 Bash 擴展進行此繞過漏洞演示的範例:

在沒有 Microsoft 公開這些問題的資訊的情況下,無法 100% 確定為何會這樣,但我可以猜測。

在對資料庫進行了大量記錄後,我相信這只是因為 SQL 欄位長度溢出,導致整個 INSERT 失敗。這是初學者在處理資料庫時常見的錯誤。

很可能解析器遍歷了包含的範圍列表,沒有發現無效的範圍,因此允許重複的條目通過,並嘗試記錄完整的 openid openid openid… 字串,從而溢出了該 SQL 欄位的限制。在測試中,可以假設合理的欄位最大長度是所有可能範圍名稱長度的總和。也許他們測試了這種情況,但從未預料到重複。

如果 Microsoft 願意公開談論此事,我很樂意聽到更多關於此事的資訊,並了解他們如何處理其最關鍵產品的內部安全審查。

很少看到實際 Azure 漏洞的演示,因為它們會被修補並永遠消失。然而,由於 Microsoft 在重現這個複雜的繞過漏洞時遇到困難,並要求提供影片,所以我帶來了證據。

為了您的觀賞樂趣,我為您呈現這可能是您將看到的唯一一個 Azure 登入記錄繞過漏洞演示:

我也在下方包含了一個傳統的逐步演練…

在接下來的演示中,我將執行一系列三次登入嘗試。

如果以下所有嘗試都已正確記錄,登入記錄應顯示:

下圖是 Entra ID 登入記錄的螢幕截圖。請注意最後一條記錄的相關 ID 和時間。日期為 2025 年 9 月 20 日,下午 1:49:20,相關 ID 以 1dfe62e9- 開頭。

在下圖中,您可以看到該失敗登入的來源;請注意時間和相關 ID 相符。

在上圖中,在失敗登入下方,您可以看到一次有效登入和時間戳。有效登入發生於 2025 年 9 月 20 日 13:52:38。這次不同的是,我使用了 GraphGoblin 繞過漏洞,這將使此登入事件不可見。登入成功,我們可以看到返回了持有者權杖。

在下一個螢幕截圖中,我將權杖匯出到變數 TOKEN,以便我們輕鬆地與 curl 一起使用。然後我透過使用該權杖發起 Graph API 請求來證明該權杖是有效的。

現在,為了在審查記錄時使其清晰,我將進行一次無效的登入嘗試,而不使用繞過漏洞。這將為我們提供一個相關 ID,作為另一個標記點。

請注意,該嘗試發生於 2025 年 9 月 20 日 19:01:45,其相關 ID 以 0d5ea4f0- 開頭。提醒您,第一次失敗登入的相關 ID 以 1dfe62e9- 開頭。

如果我們等待 10 分鐘讓記錄載入,然後審查記錄,我們會看到我們的相關 ID 以 0d5ea4f0- 開頭,緊接在我們之前相關 ID 以 1dfe62e9- 開頭的失敗登入之後。沒有顯示成功登入。

然後我進行一次正常的有效登入,不使用記錄繞過,以顯示記錄仍在流動。

我們可以看到常規的成功驗證記錄,但仍然沒有 GraphGoblin 方法的跡象。

在一段時間前將繞過漏洞的演示影片發布到 Twitter/X 後,人們好奇這是否是 Azure 入口網站 GUI 未顯示登入記錄的問題,還是記錄確實被丟棄了。

審查日誌分析後,我可以自信地說,這些記錄完全從登入記錄中被刪除了。在演示影片中,我發送了一個使用者代理為 MARKER 1 – BEFORE THE BYPASS 的正常請求。在執行了多次使用記錄繞過漏洞的驗證後,我發送了另一個使用者代理為 MARKER 2 – AFTER THE BYPASS 的正常請求。在我的日誌分析工作區中,我們可以看到沒有一個被繞過的登入記錄進入日誌分析。從我們的測試中只能看到 MARKER 1 和 MARKER 2 的條目。

好的,我提到了我發現了第四個繞過漏洞。這個漏洞非常簡單,而且與 GraphGoblin 有關。您能猜到哪個登入參數存在漏洞嗎?

我給您一個提示:這個欄位經常被自訂。

另一個提示:如果您要對關鍵的基於 Web 的驗證系統及其記錄進行模糊測試,您絕對會想將此欄位包含在您的測試中。

您猜對了嗎?如果您猜測是 USER-AGENT 欄位,您就答對了!

濫用此欄位而不產生驗證記錄的秘密是什麼?您需要讓 user-agent 字串非常長。總共 50,000 個字元的使用者代理字串可以可靠地工作。就是這樣。沒有什麼特別的技巧,只是一個長字串。

這是繞過漏洞在作用中的螢幕截圖:

同樣,我猜測這是由於 SQL 欄位長度溢出造成的。

這是一張螢幕截圖,我進行了一次失敗的登入以產生一個以 c542178e 開頭的相關 ID:

這是一張螢幕截圖,顯示了我於 2025 年 10 月 9 日在我的日誌中搜尋上個月記錄中該相關 ID 的情況。正如您所見,沒有找到具有該相關 ID 的記錄,這表明繞過漏洞已成功。

我在 2025 年 9 月 28 日發現了這個漏洞,一週後我回去撰寫報告時,Microsoft 已經修復了它!我不確定他們是如何注意到並修復這個問題,同時又沒有注意到並修復 GraphGoblin 的,但他們做到了。

Microsoft,這到底是怎麼回事?

總結一下,以下是導致 Azure Entra ID 登入記錄繞過漏洞的登入 POST 部分。我將它們匯總到一個螢幕截圖中,以便您可以看到有多少登入參數出現了問題。我將它們匯總到一個螢幕截圖中,以便您可以看到有多少登入參數出現了問題。

這是保護數百甚至數千個組織的門戶。這個關鍵功能的部分內容為何會如此嚴重地未經測試?我過去幾年提交的繞過漏洞都不複雜。然而,Microsoft 對 Entra ID 的安全審查卻錯過了所有這些。

這些問題是透過 AI 編碼引入的嗎?任何使用過 AI 編碼的人都知道,AI 在修改程式碼時 100% 會(而且經常)丟失部分程式碼。或者這些問題是多年來慢慢引入的?或者,這些問題從十多年前 Azure 開始就一直存在了?不幸的是,我們永遠不會知道。我再次邀請 Microsoft 公開談論這些一再發生的失誤。

過去三年發現了四個登入記錄繞過漏洞,而這可能是 Azure 中最重要的記錄。這對於依賴這些記錄作為真相來源的管理員來說不是一個好兆頭。那麼,除了搬回本地部署之外,您還能做些什麼?好吧,如果您花錢購買 E5 授權,儘管 Microsoft 出現了故障,您仍然可以偵測到惡意活動。

在發現最後兩個繞過漏洞後,我開始嘗試識別這些被繞過會話的流量。我一直在 Log Analytics 工作區中收集 Graph 活動以及登入記錄。在審查記錄時,我注意到登入記錄和 Graph 活動記錄都有一個 Session ID 欄位。太好了!應該可以從 Graph 活動記錄中取得所有唯一的 Session ID 列表,並在登入記錄中找到相應的 Session ID。任何僅出現在 Graph 活動記錄中,並且不存在於任何登入記錄中的 Session ID,都必須繞過了登入記錄。注意:防禦者需要 E5 授權才能收集 Graph 活動記錄。

我從一個簡單的查詢開始,在我的小型測試租戶上運行它,結果就出來了!我得到了一份屬於我被繞過會話的 Graph 活動列表。

然而,當在一個較大組織的客戶處測試偵測時,很快就發現需要考慮大量的「雜訊」。我的簡單檢查沒有考慮到非互動式登入,也沒有考慮到服務主體登入。

有一段時間,我陷入了僵局。然而,我很快發現有人已經考慮過這個問題,並已經實施了!Fabian Bader 在他的精彩文章「使用 Microsoft Graph 活動記錄偵測威脅 - 第二部分」中涵蓋了這一點。

其中有一整個部分是關於尋找遺失的登入記錄!

這種方法結合了我沒有考慮到的額外登入來源,包括來自服務主體、受控識別和非互動式使用者登入。它不是基於 SessionId 值進行 JOIN,而是基於更細粒度的屬性進行 JOIN – GraphActivity.SignInActivityId <-> SignInLogs.UniqueTokenIdentifier。

我仍然有一些雜訊,但我將 MicrosoftServicePrincipalSignInLogs 添加到登入來源列表中,大部分雜訊都清除了。

如果上述查詢返回誤報,您可能想嘗試基於更廣泛的匹配變數 SessionId 進行匹配:

如果您能夠調整查詢,使其不產生誤報,您可能想建立一個 Azure 日誌搜尋警報規則,以便在出現警報時通知您。

我強烈建議您查看 Bader 部落格的其餘部分,以獲取更多偵測想法,因為該文章是三部曲部落格系列的一部分。

在完全出乎意料的事件發展中,Microsoft 通知我,他們認為這不是一個「重要」問題,而僅僅是一個「中度」安全問題。因此,它不符合任何確認或獎勵的資格。

我感到震驚。在我之前兩次識別 Azure Entra Sign-In 記錄繞過漏洞時,他們都給了我獎勵,而且那時的繞過漏洞功能還不如這次。

提交給 Microsoft 時,他們會要求您評估其 CVSS 分數。以下是我對分數的評估以及原因。如果您想跳過技術細節,可以直接跳到下面的偵測部分。

將隱藏失敗和成功的登入記錄

關鍵記錄被繞過 - 請參閱下方的注意事項

完整性評級是這個問題的核心,這也是為什麼它在 Microsoft 的術語中應該被評為「重要」的原因。如果我們查閱 CVSS v3.1 文件,可以看到他們舉例說明了什麼構成完整性指標的低或高。

在描述完整性指標的「高」值時,指南指出:「完整性完全喪失,或保護完全喪失。例如,攻擊者能夠修改受影響組件保護的任何/所有檔案。或者,只能修改某些檔案,但惡意修改將對受影響組件產生直接、嚴重的後果。」

在這裡,我們透過導致記錄被省略來修改 Azure Entra ID 登入記錄。修改這些登入記錄對受影響的組件產生了直接、嚴重的後果。

將所有這些輸入計算器,我們看到結果是「高」,CVSS v3.1 分數為 7.5。

如果我們在 CVSS v4.0 中計算,它包含與完整性指標相同的語言,我們得到更高的評級 8.7。

儘管 Microsoft 聲稱這不是「重要」的嚴重性,但他們在創紀錄的時間內修復了它。雖然他們一開始在重現漏洞時遇到困難,但在我提供影片演示和工具後,他們在兩週內就修復了問題。作為參考,GraphNinja 花了他們七個月,GraphGhost 花了五個月。

也許最糟糕的方面是這種不一致性。您完全不知道他們會怎麼做,不知道他們會如何看待您的問題(或他們對問題的理解程度),也無法保證您是否會從您的麻煩和故障排除中獲得任何回報。

下表描述了我發現的四個繞過漏洞以及 MSRC 的處理方式。Microsoft 沒有公開承認任何登入記錄繞過漏洞。

獎勵?(「重要」或更高)

透過指定外部租戶 ID 作為端點,在不建立記錄的情況下驗證密碼

透過提供特定登入參數的無效值,導致整體驗證流程在執行憑證驗證後失敗,從而繞過成功登入事件的記錄

透過重複一個有效參數值 35,000 次,溢出表格欄位,在不建立記錄的情況下取得權杖

透過指定非常長的 user-agent 字串,溢出表格欄位,在不建立記錄的情況下取得權杖

儘管 GraphGoblin 擷取了完整的權杖,但他們現在決定這些「不重要」。

起初,Microsoft 發放 CVE,這很好。CVE > 獎勵,因為 CVE 是永久的。我在 2017 年和 2018 年為 Skype for Business 和 Lync for Mac 獲得了幾個 CVE,但沒有獎勵。然後,Microsoft 放慢了發放 CVE 的速度,但開始發放獎勵。雲端產品沒有 CVE,而且只針對高或嚴重級別。這不太好,但我意識到我有一些物質需求,所以現金也還可以。

但現在,Microsoft 什麼也沒給我。沒有獎勵。沒有他們虛擬積分板上的虛擬積分。甚至沒有確認。Microsoft 是 CNA,他們可以決定什麼是漏洞,什麼不是,據我所知,沒有真正的申訴途徑。這是一種方便的安排,讓他們可以決定哪些失敗可以公開,哪些可以被掩蓋。

他們在問題是否被歸類為「重要」方面的退縮令人沮喪。我會說,如果他們沒有對最初的 GraphNinja 繞過漏洞給予獎勵,我不知道我是否會投入相同的時間和精力去尋找其他漏洞。我們都有忙碌的生活,包括我。如果他們沒有支付第一個獎勵,那麼很可能會有 3 個未被發現的繞過漏洞等待著攻擊者去利用。

總之,我想讓您再次看看這個螢幕截圖,並注意過去幾年影響 Entra 登入記錄的失敗之處。

這些都不是複雜的記錄繞過。這些都是簡單的模糊測試的結果。此外,這不僅僅是任何記錄被繞過,而是對整個 Azure 租戶安全至關重要的關鍵記錄。一個饋送到 SIEM 並被用作偵測入侵者真相來源的記錄。這些嚴重的安全漏洞是如何引入的?它們存在了多久?為什麼 Microsoft 自己的審查沒有發現它們?美國幾乎所有地方都使用 Azure。世界許多地方都使用 Azure。我們共同將信任寄託在 Microsoft 及其安全實踐上。當出現影響如此多用戶的問題時,我認為 Microsoft 有義務向公眾廣泛告知。不幸的是,我們沒有看到這一點。