Compartilhar via


Migrar para longe do uso de declarações de email para identificação ou autorização do usuário

O objetivo deste artigo é fornecer orientação aos desenvolvedores cujos aplicativos estão usando atualmente um padrão inseguro em que a reivindicação de email é utilizada para autorização, o que pode levar ao controle total da conta por outro usuário. Continue lendo para saber mais sobre se o aplicativo foi afetado e as etapas para correção.

Como posso saber se o meu aplicativo foi afetado?

A Microsoft recomenda revisar o código-fonte do aplicativo e determinar se os seguintes padrões estão presentes:

  • Uma declaração mutável, como email, é usada para fins de identificar exclusivamente um usuário
  • Uma declaração mutável, como email é usada para fins de autorizar o acesso de um usuário aos recursos

Esses padrões são considerados inseguros, pois os usuários sem uma caixa de correio provisionada podem ter qualquer endereço de email definido para o atributo Email (SMTP Primário). Não é garantido que esse atributo seja proveniente de um endereço de email verificado. Quando uma reivindicação de email com um proprietário de domínio não verificado é utilizada para autorização, qualquer usuário sem uma caixa de correio provisionada tem a possibilidade de obter acesso não autorizado alterando o atributo Email para se passar por outro usuário.

Um email será considerado proprietário do domínio verificado se:

  • O domínio pertence ao locatário no qual a conta de usuário reside, e o administrador do locatário fez a verificação do domínio
  • O email é de uma Conta Microsoft (MSA)
  • O email é de uma conta do Google
  • O email foi usado para autenticação usando o fluxo de senha de uso único (OTP)

Observe também que as contas do Facebook e SAML/WS-Fed não têm domínios verificados.

Esse risco de acesso não autorizado só foi encontrado em aplicativos multilocatários, pois um usuário de um locatário pode escalonar seus privilégios para acessar recursos de outro locatário por meio da modificação de seu atributo Mail.

Como fazer para proteger meu aplicativo imediatamente?

Para proteger os aplicativos contra erros com endereços de email não verificados, todos os novos aplicativos multilocatários são automaticamente incluídos em um novo comportamento padrão que remove os endereços de email com proprietários de domínio não verificados dos tokens a partir de junho de 2023. Esse comportamento não está habilitado para aplicativos de locatário único e aplicativos de vários locatários com atividade de entrada anterior com endereços de email não verificados do proprietário do domínio.

Dependendo do seu cenário, você poderá determinar que os tokens do seu aplicativo devem continuar recebendo emails não verificados. Embora não seja recomendado para a maioria dos aplicativos, você pode desabilitar o comportamento padrão definindo a propriedade removeUnverifiedEmailClaim no objeto authenticationBehaviors da API de aplicativos no Microsoft Graph.

Ao definir removeUnverifiedEmailClaim como false, seu aplicativo receberá email declarações que podem não ser verificadas e que sujeitam os usuários ao risco de sequestro de contas. Se você estiver desabilitando esse comportamento para não interromper os fluxos de logon do usuário, é altamente recomendável migrar para um mapeamento de reivindicação de token de identificação exclusiva o mais rápido possível, conforme descrito nas diretrizes abaixo.

Identificação de configurações inseguras e realização da migração de banco de dados

Você nunca deve usar declarações mutáveis (como email, preferred_username, etc.) como identificadores para executarem verificações de autorização ou indexarem usuários em um banco de dados. Esses valores são reutilizáveis e podem expor seu aplicativo a ataques de escalonamento de privilégios.

O exemplo de pseudocódigo a seguir ajuda a ilustrar o padrão inseguro de identificação / autorização do usuário:

 // 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
 }

Após determinar que o aplicativo depende desse atributo inseguro, é necessário atualizar a lógica de negócios para reindexar os usuários com base em um identificador globalmente exclusivo (GUID).

Os aplicativos multilocatários devem ser indexados em um mapeamento de duas reivindicações de identificação exclusiva, tid + oid. Isso segmentará os locatários por tid e os usuários por seus oid.

Usando a reivindicação opcional xms_edov para determinar o status de verificação de email e migrar usuários

Para ajudar os desenvolvedores no processo de migração, introduzimos uma declaração opcional, xms_edov, uma propriedade booleana que indica se o proprietário do domínio de email foi ou não verificado.

xms_edov pode ser utilizado para ajudar a verificar o email de um usuário antes de migrar sua chave primária para identificadores exclusivos, como oid. O exemplo de pseudocódigo a seguir ilustra como essa declaração pode ser utilizada como parte da sua migração.

// 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
}

A migração para um mapeamento globalmente exclusivo garante que cada usuário seja indexado principalmente com um valor que não possa ser reutilizado ou abusado para se passar por outro usuário. Depois que seus usuários forem indexados em um identificador globalmente exclusivo, você estará pronto para corrigir qualquer lógica de autorização em potencial que utilize a declaração email.

Atualizar a lógica de autorização com a devida validação das declarações

Se seu aplicativo usa email (ou qualquer outra reivindicação mutável) para fins de autorização, você deve fazer uma leitura dos aplicativos e APIs seguros, validando as reivindicações e implementar as verificações apropriadas.

Próximas etapas