다음을 통해 공유


보안 권고: Microsoft Entra 인증에 대한 역할 할당 업데이트

몰입형 리더 대한 Microsoft Entra 인증에 영향을 주는 보안 버그가 발견되었습니다. 몰입형 리더 리소스에 대한 사용 권한을 변경하는 것이 좋습니다.

배경

처음에 몰입형 리더 리소스를 만들고 Microsoft Entra 인증을 위해 구성하는 경우 Microsoft Entra 애플리케이션 ID가 몰입형 리더 리소스에 액세스할 수 있는 권한을 부여해야 합니다. 이를 역할 할당이라고 합니다. 이전에 권한에 사용된 Azure 역할은 Cognitive Services 사용자 역할이었습니다.

보안 감사 중에 이 Cognitive Services 사용자 역할에 키를 나열할 수 있는 권한이 있는 것으로 확인되었습니다. 몰입형 리더 통합에는 클라이언트 웹앱 및 브라우저에서 이 Microsoft Entra 액세스 토큰을 사용하는 것이 포함되므로 이는 약간 관련이 있습니다. 악의적인 행위자 또는 공격자가 액세스 토큰을 도난당한 경우 이 액세스 토큰을 몰입형 리더 리소스에 list keys 사용할 수 있다는 우려가 있습니다. 공격자가 리소스에 대해 list keys할 수 있는 경우 해당 리소스의 Subscription Key에 대한 정보를 얻을 수 있습니다. 리소스에 대한 Subscription Key는 인증 메커니즘으로 사용되며 비밀로 간주됩니다. 공격자가 리소스의 Subscription Key를 사용하는 경우 Immersive Reader 리소스 엔드포인트에 대해 유효하고 인증된 API를 호출할 수 있으며, 이로 인한 엔드포인트의 사용량 및 제한 증가로 서비스 거부가 발생할 수 있습니다. 또한 Immersive Reader 리소스를 무단으로 사용할 수 있으므로 청구서에 대한 요금이 증가합니다.

그러나 실제로는 이 공격 또는 악용이 발생할 가능성이 없거나 가능하지 않을 수도 있습니다. 몰입형 리더 시나리오의 경우 고객은 대상 https://cognitiveservices.azure.com그룹과 함께 Microsoft Entra 액세스 토큰을 얻습니다. 리소스를 성공적으로 list keys 사용하려면 Microsoft Entra 액세스 토큰에 대상 https://management.azure.com을 포함해야 합니다. 일반적으로 몰입형 리더 시나리오에 사용되는 액세스 토큰은 필요한 대상을 갖지 않으므로 작동하지 list keys않으므로 별로 문제가 되지 않습니다. 액세스 토큰에서 대상 그룹을 변경하려면 공격자가 토큰 획득 코드를 하이재킹하고 토큰을 획득하기 위해 Microsoft Entra ID를 호출하기 전에 대상 그룹을 변경해야 합니다. 다시 말하지만, 몰입형 리더 인증 모범 사례로 고객이 클라이언트 또는 브라우저가 아닌 웹 애플리케이션 백 엔드에서 Microsoft Entra 액세스 토큰을 만드는 것이 좋습니다. 이러한 경우 토큰 획득이 백 엔드 서비스에서 발생하므로 공격자가 해당 프로세스를 손상시키고 대상 그룹을 변경할 수 있는 가능성이나 가능성도 없습니다.

실제 문제는 고객이 클라이언트 코드에서 직접 Microsoft Entra ID에서 토큰을 획득해야 하는 경우 발생합니다. 이에 대해 강력하게 조언하지만, 고객이 적합해 보이는 대로 자유롭게 구현할 수 있으므로 일부 고객이 이 작업을 수행할 수 있습니다.

Microsoft Entra 액세스 토큰을 사용할 가능성에 대한 우려를 완화하기 위해 list keys권한이 list keys없는 새 기본 제공 Azure 역할을 Cognitive Services Immersive Reader User 만들었습니다. 이 새 역할은 역할과 같은 Cognitive Services User Azure AI 서비스 플랫폼에 대한 공유 역할이 아닙니다. 이 새 역할은 몰입형 리더 전용이며 몰입형 리더 API에 대한 호출만 허용합니다.

모든 고객에게 원래 Cognitive Services User 역할 대신 새 Cognitive Services Immersive Reader User 역할을 사용하는 것이 좋습니다. 역할 할당 권한을 전환하기 위해 각 리소스에서 실행할 수 있는 아래 스크립트를 제공했습니다.

이 권장 사항은 구현 시나리오 또는 공격 가능성에 관계없이 모든 사용자에게 이 취약성이 패치되도록 모든 고객에게 적용됩니다.

이 작업을 수행하지 않으면 아무 것도 중단되지 않습니다. 이전 역할은 계속 작동합니다. 대부분의 고객에 대한 보안 영향은 최소화됩니다. 그러나 논의된 보안 문제를 완화하기 위해 새 역할로 마이그레이션하는 것이 좋습니다. 이 업데이트를 적용하는 것은 보안 권고 권장 사항입니다. 그것은 위임이 아닙니다.

스크립트를 사용하여 만드는 모든 새 몰입형 리더 리소스는 방법: 몰입형 리더 리소스 만들기에서 새 역할을 자동으로 사용합니다.

역할 업데이트 및 구독 키 회전

방법: 2022년 2월 이전에 몰입형 리더 리소스 만들기의 지침을 사용하여 몰입형 리더 리소스를 만들고 구성한 경우 다음 작업을 수행하여 모든 몰입형 리더 리소스에 대한 역할 할당 권한을 업데이트하는 것이 좋습니다. 작업에는 단일 리소스에 대한 역할 할당을 업데이트하는 스크립트 실행이 포함됩니다. 리소스가 여러 개 있는 경우 각 리소스에 대해 한 번씩 이 스크립트를 여러 번 실행합니다.

다음 스크립트를 사용하여 역할을 업데이트한 후에는 리소스에서 구독 키를 회전하는 것이 좋습니다. 이 경우 키가 악용에 의해 손상되었으며 누군가가 실제로 사용자의 동의 없이 구독 키 인증으로 리소스를 사용하고 있는 경우입니다. 키를 회전하면 이전 키가 유효하지 않으며 추가 액세스가 거부됩니다. 현재 몰입형 리더 SDK 구현당 모든 사용자여야 하는 Microsoft Entra 인증을 사용하는 고객의 경우 Microsoft Entra 액세스 토큰이 구독 키가 아닌 인증에 사용되므로 키 회전은 몰입형 리더 서비스에 영향을 주지 않습니다. 구독 키를 회전하는 것은 또 다른 예방 조치입니다.

Azure Portal에서 구독 키를 회전할 수 있습니다. 리소스로 이동한 다음 섹션으로 Keys and Endpoint 이동합니다. 맨 위에는 Regenerate Key1Regenerate Key2하기 위한 단추가 있습니다.

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

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 Immersive Reader 리소스의 이름입니다.
    AADAppIdentifierUri Microsoft Entra 앱의 URI입니다.

다음 단계