針對使用者識別或授權移轉,不使用電子郵件宣告
本文旨在為應用程式目前使用不安全模式的開發人員提供指導,該模式使用電子郵件宣告進行授權,可能導致其他使用者完全接管帳戶。 繼續閱讀,深入了解您的應用程式是否受到影響,以及補救步驟。
如何判斷我的應用程式是否受影響?
Microsoft 建議您,檢閱應用程式原始程式碼,並判斷是否有下列模式:
- 可變動宣告,例如
email
,用於唯一識別使用者之目的 - 可變動宣告,例如
email
,用於授權使用者存取資源之目的
這些模式被視為不安全,因為沒有佈建信箱的使用者,可以為其郵件 (主要 SMTP) 屬性設定任何電子郵件位址。 此屬性不保證來自已驗證的電子郵件地址。 具有未驗證網域擁有者的電子郵件宣告用於授權時,任何沒有已佈建信箱的使用者,都有可能藉由變更其 Mail 屬性模擬其他使用者,取得未經授權的存取權。
如果出現下列狀況,電子郵件便視同通過網域擁有者驗證:
- 網域屬於使用者帳戶所在的租用戶,而租用戶系統管理員已完成網域的驗證
- 電子郵件來自 Microsoft帳戶 (MSA)
- 電子郵件來自 Google 帳戶
- 電子郵件用於使用一次性密碼 (OTP) 流程進行驗證
此外,請注意,Facebook 和 SAML/WS-Fed 帳戶沒有已驗證的網域。
只有多租用戶應用程式才有未經授權存取的風險,因為一個租用戶的使用者,透過修改其 Mail 屬性即可提升其權限,從另一個租用戶存取資源。
如何立即保護我的應用程式?
為保護應用程式免於發生未驗證電子郵件地址的錯誤,截至 2023 年 6 月,所有新的多租用戶應用程式都會自動選擇加入新的預設行為,從權杖移除具有未驗證網域擁有者的電子郵件位址。 單一租用戶應用程式,以及有曾以使用網域擁有者未驗證電子郵件位址登入活動的多租用戶應用程式,未啟用此行為。
視您的案例而定,您可能判斷應用程式的權杖應該繼續接收未經驗證的電子郵件。 雖然不建議大多數應用程式使用,但您可以在 Microsoft Graph 中設定應用程式 API authenticationBehaviors 物件的 removeUnverifiedEmailClaim
屬性,停用預設行為。
將 removeUnverifiedEmailClaim
設定為 false
,應用程式會收到可能未經驗證的 email
宣告,讓使用者面臨帳戶接管的風險。 如果您要停用此行為,以免中斷使用者登入流程,強烈建議您儘快移轉至唯一識別權杖宣告對應,如下列指導所述。
識別不安全的組態並執行資料庫移轉
您絕對不應該使用可變動宣告 (例如 email
和 preferred_username
等) 作為識別碼,以在資料庫中執行授權檢查或編製使用者索引。 這些值可重複使用,而且可能會向權限提升攻擊公開您的應用程式。
下列虛擬程式碼範例可協助說明使用者識別 / 授權不安全的模式:
// Your relying party (RP) using the insecure email claim for user identification (or authorization)
MyRPUsesInsecurePattern()
{
// grab data for the user based on the email (or other mutable) attribute
data = GetUserData(token.email)
// Create new record if no data present (This is the anti-pattern!)
if (data == null)
{
data = WriteNewRecords(token.email)
}
insecureAccess = data.show // this is how an unverified user can escalate their privileges via an arbirarily set email
}
一旦您判斷應用程式正採用這個不安全的屬性,您必須更新商務邏輯,以通用唯一識別碼 (GUID) 重新編製使用者的索引。
多租用戶應用程式應該針對兩個唯一識別宣告 tid
+ oid
的對應編製索引。 這會依 tid
區隔租用戶,並以其 oid
區隔使用者。
使用 xms_edov
選擇性宣告來判斷電子郵件驗證狀態及移轉使用者
為了協助開發人員進行移轉流程,我們引進了選擇性宣告 xms_edov
,這個布林值屬性會指出電子郵件網域擁有者是否已驗證。
xms_edov
可用來協助驗證使用者的電子郵件,再將其主索引鍵移轉至唯一識別碼,例如 oid
。 下列虛擬程式碼範例說明,此宣告如何作為移轉的一部分使用。
// Verify email and migrate users by performing lookups on tid+oid, email, and xms_edov claims
MyRPUsesSecurePattern()
{
// grab the data for a user based on the secure tid + oid mapping
data = GetUserData(token.tid + token.oid)
// address case where users are still indexed by email
if (data == null)
{
data = GetUserData(token.email)
// if still indexed by email, update user's key to GUID
if (data != null)
{
// check if email domain owner is verified
if (token.xms_edov == false)
{
yourEmailVerificationLogic()
}
// migrate primary key to unique identifier mapping (tid + oid)
data.UpdateKeyTo(token.tid + token.oid)
}
// new user, create new record with the correct (secure) key
data = WriteNewRecord(token.sub)
}
secureAccess = data.show
}
移轉至全域唯一的對應,可確保每個使用者主要以無法重複使用的值編製索引,或是以無法濫用以模擬其他使用者的值編製索引。 一旦以通用唯一識別碼編製使用者索引,您就可以修正任何使用 email
宣告的潛在授權邏輯。
使用適當的宣告驗證更新授權邏輯
如果您的應用程式使用 email
(或任何其他可變動宣告) 進行授權,您應該仔細閱讀藉由驗證宣告來保護應用程式和 API,並實作適當的檢查。
下一步
- 若要進一步了解如何安全使用宣告型授權,請參閱藉由驗證宣告來保護應用程式和 API (部分為機器翻譯)
- 如需選擇性宣告的詳細資訊,請參閱選擇性宣告參考