安全性諮詢:更新 Microsoft Entra 驗證許可權的角色指派

沉浸式閱讀程式 Microsoft Entra 驗證設定已探索到安全性錯誤。 建議您變更沉浸式閱讀程式資源的許可權,如下所示。

背景

發現與 Microsoft Entra 驗證相關的安全性錯誤沉浸式閱讀程式。 一開始建立沉浸式閱讀程式資源並設定這些資源以進行 Microsoft Entra 驗證時,必須授與 Microsoft Entra 應用程式身分識別的許可權,才能存取您的沉浸式閱讀程式資源。 這稱為角色指派。 先前用於許可權的 Azure 角色是認知服務使用者 角色。

在安全性稽核期間,探索到此 認知服務使用者角色具有列出金鑰的權限。 這有點令人擔心,因為沉浸式閱讀程式整合牽涉到在用戶端 Web 應用程式和瀏覽器中使用此 Microsoft Entra 存取權杖,而且如果存取權杖被不良動作專案或攻擊者竊取,則擔心此存取權杖可用於 list keys 您的沉浸式閱讀程式資源。 如果攻擊者可以 list keys 針對您的資源,則他們會取得 Subscription Key 資源的 。 Subscription Key資源的 會當做驗證機制使用,並視為秘密。 如果攻擊者擁有資源的 Subscription Key ,則會允許他們對您的沉浸式閱讀程式資源端點進行有效且已驗證的 API 呼叫,這可能會導致拒絕服務,因為端點的使用量和節流增加。 它也允許未經授權使用您的沉浸式閱讀程式資源,這會導致帳單費用增加。

不過,在實務上,此攻擊或惡意探索不太可能發生或甚至不可能發生。 針對沉浸式閱讀程式案例,客戶會以 的物件 https://cognitiveservices.azure.com 取得 Microsoft Entra 存取權杖。 若要成功 list keys 為您的資源使用,Microsoft Entra 存取權杖必須有 的物件 https://management.azure.com 。 一般而言,這不是太多問題,因為用於沉浸式閱讀程式案例的存取權杖無法運作 list keys ,因為它們沒有所需的物件。 若要變更存取權杖上的物件,攻擊者必須劫持權杖取得程式碼,並在呼叫 Microsoft Entra ID 之前變更物件,以取得權杖。 同樣地,這不太可能遭到惡意探索,因為基於沉浸式閱讀程式驗證最佳做法,我們建議客戶在 Web 應用程式後端建立 Microsoft Entra 存取權杖,而不是在用戶端或瀏覽器中。 在這些情況下,由於權杖擷取發生在後端服務上,因此攻擊者可能無法入侵該程式並變更物件。

當任何客戶是否要直接在用戶端程式代碼中從 Microsoft Entra ID 取得權杖時,就會真正感到擔憂。 我們強烈建議不要這麼做,但因為客戶可以自由實作,因為他們認為適合,所以有些客戶可能會這麼做。

為了減輕對 使用 Microsoft Entra 存取權杖 list keys 之任何可能性的擔憂,我們已建立名為 Cognitive Services Immersive Reader User 的新內建 Azure 角色,且沒有 許可權 list keys 。 這個新角色不像 Cognitive Services User 角色那樣是 Azure AI 服務平台的共用角色。 這個新角色專屬於沉浸式閱讀程式,而且只允許呼叫 沉浸式閱讀程式 API。

我們建議所有客戶移轉至使用新 Cognitive Services Immersive Reader User 角色,而不是原始 Cognitive Services User 角色。 我們提供了下列腳本,您可以在每個資源上執行,以切換角色指派許可權。

這項建議適用于 ALL 客戶,以確保無論實作案例或攻擊的可能性為何,都會針對所有人修補此弱點。

如果您不這麼做,則不會中斷任何動作。 舊角色會繼續運作。 對大多數客戶的安全性影響最低。 不過,建議您移轉至新角色,以減輕上述的安全性考慮。 套用此更新是安全性諮詢建議;這不是一項授權。

您在如何:建立沉浸式閱讀程式資源時,使用我們的腳本 建立的任何新沉浸式閱讀程式資源 ,都會自動使用新的角色。

喚起行動

如果您使用如何:在 2022 年 2 月之前建立沉浸式閱讀程式資源中的指示 建立和設定沉浸式閱讀程式資源 ,建議您執行下列作業,以更新您所有沉浸式閱讀程式資源的角色指派許可權。 此作業牽涉到執行腳本來更新單一資源上的角色指派。 如果您有多個資源,請針對每個資源執行此腳本多次。

使用下列腳本更新角色之後,也建議您在資源上輪替訂用帳戶金鑰。 以防您的金鑰遭到上述惡意探索入侵,而有人實際上在未經同意的情況下,使用您的資源搭配訂用帳戶金鑰驗證。 輪替金鑰會使先前的金鑰無效,並拒絕任何進一步的存取。 對於使用 Microsoft Entra 驗證的客戶,這應該是每個目前沉浸式閱讀程式 SDK 實作的每個人,輪替金鑰不會影響沉浸式閱讀程式服務,因為 Microsoft Entra 存取權杖用於驗證,而不是訂用帳戶金鑰。 輪替訂用帳戶金鑰只是另一個預防措施。

您可以在Azure 入口網站 輪替訂用帳戶金鑰。 流覽至您的資源,然後流覽至 Keys and Endpoint 刀鋒視窗。 在頂端,有 和 Regenerate Key2 的按鈕 Regenerate Key1

Screenshot of the Azure portal showing an Immersive Reader resource with the Keys and Endpoint blade selected, which shows the Regenerate Keys buttons at the top.

使用 Azure PowerShell 環境更新沉浸式閱讀程式資源角色指派

  1. 從開啟 Azure Cloud Shell 開始。 請確定 Cloud Shell 在左上角的下拉式清單中設定為 PowerShell,或輸入 pwsh

  2. 將下列程式碼片段複製並貼到殼層中。

    function Update-ImmersiveReaderRoleAssignment(
        [Parameter(Mandatory=$true, Position=0)] [String] $SubscriptionName,
        [Parameter(Mandatory=$true)] [String] $ResourceGroupName,
        [Parameter(Mandatory=$true)] [String] $ResourceName,
        [Parameter(Mandatory=$true)] [String] $AADAppIdentifierUri
    )
    {
        $unused = ''
        if (-not [System.Uri]::TryCreate($AADAppIdentifierUri, [System.UriKind]::Absolute, [ref] $unused)) {
            throw "Error: AADAppIdentifierUri must be a valid URI"
        }
    
        Write-Host "Setting the active subscription to '$SubscriptionName'"
        $subscriptionExists = Get-AzSubscription -SubscriptionName $SubscriptionName
        if (-not $subscriptionExists) {
            throw "Error: Subscription does not exist"
        }
        az account set --subscription $SubscriptionName
    
        # Get the Immersive Reader resource 
        $resourceId = az cognitiveservices account show --resource-group $ResourceGroupName --name $ResourceName --query "id" -o tsv
        if (-not $resourceId) {
            throw "Error: Failed to find Immersive Reader resource"
        }
    
        # Get the Azure AD application service principal
        $principalId = az ad sp show --id $AADAppIdentifierUri --query "objectId" -o tsv
        if (-not $principalId) {
            throw "Error: Failed to find Azure AD application service principal"
        }
    
        $newRoleName = "Cognitive Services Immersive Reader User"
        $newRoleExists = az role assignment list --assignee $principalId --scope $resourceId --role $newRoleName --query "[].id" -o tsv
        if ($newRoleExists) {
            Write-Host "New role assignment for '$newRoleName' role already exists on resource"
        } 
        else {
            Write-Host "Creating new role assignment for '$newRoleName' role"
            $roleCreateResult = az role assignment create --assignee $principalId --scope $resourceId --role $newRoleName
            if (-not $roleCreateResult) {
                throw "Error: Failed to add new role assignment"
            }
            Write-Host "New role assignment created successfully"
        }
    
        $oldRoleName = "Cognitive Services User"
        $oldRoleExists = az role assignment list --assignee $principalId --scope $resourceId --role $oldRoleName --query "[].id" -o tsv
        if (-not $oldRoleExists) {
            Write-Host "Old role assignment for '$oldRoleName' role does not exist on resource"
        }
        else {
            Write-Host "Deleting old role assignment for '$oldRoleName' role"
            az role assignment delete --assignee $principalId --scope $resourceId --role $oldRoleName
            $oldRoleExists = az role assignment list --assignee $principalId --scope $resourceId --role $oldRoleName --query "[].id" -o tsv
            if ($oldRoleExists) {
                throw "Error: Failed to delete old role assignment"
            }
            Write-Host "Old role assignment deleted successfully"
        }
    }
    
  3. 執行 函式 Update-ImmersiveReaderRoleAssignment ,並視需要提供下方的 ' < PARAMETER_VALUES > ' 預留位置,並視情況使用您自己的值。

    Update-ImmersiveReaderRoleAssignment -SubscriptionName '<SUBSCRIPTION_NAME>' -ResourceGroupName '<RESOURCE_GROUP_NAME>' -ResourceName '<RESOURCE_NAME>' -AADAppIdentifierUri '<AAD_APP_IDENTIFIER_URI>'
    

    完整的命令看起來會像下面這樣。 在這裡,我們已將每個參數放在自己的行,以便清楚瞭解,因此您可以看到整個命令。 請勿依目前身分複製或使用此命令。 複製並使用上述命令搭配您自己的值。 此範例具有上述 ' < PARAMETER_VALUES > ' 的虛擬值。 您的 會有所不同,因為您將針對這些值想出自己的名稱。

    Update-ImmersiveReaderRoleAssignment
    -SubscriptionName 'MyOrganizationSubscriptionName'
    -ResourceGroupName 'MyResourceGroupName'
    -ResourceName 'MyOrganizationImmersiveReader'
    -AADAppIdentifierUri 'https://MyOrganizationImmersiveReaderAADApp'

    參數 註解
    SubscriptionName 您 Azure 訂用帳戶的名稱。
    resourceGroupName 包含沉浸式閱讀程式資源的資源群組名稱。
    ResourceName 沉浸式閱讀程式資源的名稱。
    AADAppIdentifierUri Azure AD 應用程式的 URI。

下一步