分享方式:


安全性公告:更新 Microsoft Entra 驗證的角色指派

我們發現了影響沈浸式閱讀程式 Microsoft Entra 驗證的安全性 Bug。 我們建議您在沈浸式閱讀程式資源變更權限。

背景

您一開始建立沈浸式閱讀程式資源並設定進行 Microsoft Entra 驗證時,必須授與權限給 Microsoft Entra 應用程式識別碼以存取沈浸式閱讀程式資源。 這稱為角色指派。 先前用於權限的 Azure 角色是認知服務使用者角色。

在安全性稽核期間,發現此認知服務使用者角色具有列出金鑰的權限。 這有點令人擔心,因為沈浸式閱讀程式整合牽涉在用戶端 Web Apps 和瀏覽器中使用此 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 角色。 我們已提供下列指令碼,您可以在每個資源上執行該指令碼,以切換角色指派權限。

此建議適用於所有客戶,以確保不論實作情節或攻擊的可能性為何,每個人都會修補此弱點。

如果您沒有這樣做,則不會中斷任何項目。 舊角色仍會繼續運作。 對大部分客戶的安全性影響很小。 不過我們建議您移轉至新的角色,以減輕前面討論的安全性顧慮。 套用此更新是安全性公告建議,並不是命令。

您已在操作說明:建立沈浸式閱讀程式資源中使用我們的指令碼建立的任何新沈浸式閱讀程式資源,都會自動使用新的角色。

更新角色並輪替您的訂用帳戶金鑰

如果您已在 2022 年 2 月之前使用操作說明:建立沈浸式閱讀程式資源中的指示,建立和設定沈浸式閱讀程式資源,我們建議您執行下列作業,以更新所有沈浸式閱讀程式資源的角色指派權限。 作業涉及執行指令碼,以更新單一資源上的角色指派。 如果您有多個資源,請執行此指令碼多次,每個資源一次。

您使用下列指令碼更新角色之後,我們也建議您在資源上輪換訂用帳戶金鑰。 這是為了防止您的金鑰因惡意探索遭到入侵,且有人未經您同意以訂用帳戶金鑰驗證實際使用您的資源。 輪換金鑰會使得先前的金鑰無效,並拒絕任何進一步的存取。 對於使用 Microsoft Entra 驗證的客戶 (根據目前沈浸式閱讀程式 SDK 實作應該是每個人),輪換金鑰不會影響沈浸式閱讀程式服務,因為 Microsoft Entra 存取權杖用於驗證,而不是訂用帳戶金鑰。 輪換訂用帳戶金鑰只是另一個預防措施。

您可以在 Azure 入口網站輪換訂用帳戶金鑰。 瀏覽至您的資源,然後前往 Keys and Endpoint 區段。 頂端有 Regenerate Key1Regenerate Key2 的按鈕。

Azure 入口網站的螢幕擷取畫面:其中顯示沉浸式閱讀程式資源,並已選取 [金鑰和端點] 區段,頂端顯示 [重新產生金鑰] 按鈕。

使用 Azure PowerShell 更新您的角色指派

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

  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 Microsoft Entra application service principal
        $principalId = az ad sp show --id $AADAppIdentifierUri --query "objectId" -o tsv
        if (-not $principalId) {
            throw "Error: Failed to find Microsoft Entra 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 '<MICROSOFT_ENTRA_APP_IDENTIFIER_URI>'
    

    完整命令看起來會像下面這樣。 為了清楚起見,我們將每個參數放在參數本身的行上,因此您可以看到整個命令。 請不要依現況複製或使用此命令。 複製命令並搭配您自己的值使用此命令。 此範例具有 <PARAMETER_VALUES> 的虛擬值。 您的值會有所不同,因為您會為這些值提出自己的名稱。

    Update-ImmersiveReaderRoleAssignment
        -SubscriptionName 'MyOrganizationSubscriptionName'
        -ResourceGroupName 'MyResourceGroupName'
        -ResourceName 'MyOrganizationImmersiveReader'
        -AADAppIdentifierUri 'https://MyOrganizationImmersiveReaderAADApp'
    
    參數 註解
    SubscriptionName 您 Azure 訂用帳戶的名稱。
    resourceGroupName 包含沈浸式閱讀程式資源的資源群組名稱。
    ResourceName 沈浸式閱讀程式資源的名稱。
    AADAppIdentifierUri Microsoft Entra 應用程式的 URI。

後續步驟