보안 권고: 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 리소스를 무단으로 사용할 수 있으므로 청구서에 대한 요금이 증가합니다.
그러나 실제로 이 공격이나 악용은 발생할 가능성이 낮거나, 전혀 불가능할 수도 있습니다. 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에서 직접 토큰을 획득해야 하는 시기 또는 경우에 발생합니다. 이에 반대할 것을 강력하게 권장하지만, 고객이 적합하다고 생각하는 대로 자유롭게 구현할 수 있으므로 일부 고객은 이 작업을 수행할 수도 있습니다.
list keys
에 Microsoft Entra 액세스 토큰을 사용할 가능성에 대한 우려를 완화하기 위해 list keys
권한이 없는, Cognitive Services Immersive Reader User
라는 새로운 기본 제공 Azure 역할을 만들었습니다. 이 새 역할은 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 Key1
및 Regenerate Key2
하기 위한 단추가 있습니다.
Azure PowerShell을 사용하여 역할 할당 업데이트
Azure Cloud Shell을 열어 시작합니다. 왼쪽 위의 드롭다운에서 또는
pwsh
를 입력하여 Cloud Shell이 PowerShell로 설정되어 있는지 확인합니다.다음 코드 조각을 복사하여 셸에 붙여넣습니다.
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" } }
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입니다.