Um breve resumo da segurança do OAuth
Quão bem versado você está nas medidas de proteção empregadas pelo OAuth? Seu sistema adere ao padrão aberto do OAuth? Você está ciente dos possíveis riscos que podem surgir durante a implementação do fluxo de autenticação do usuário? Vamos recapitular brevemente o que aprendemos sobre o OAuth.
Introdução
Há alguns dias, um artigo interessante sobre vulnerabilidade OAuth nos atingiu. [A-new-oauth-vulnerability-that-may-impact-hundreds-of-online-services] (https://salt.security/blog/a-new-oauth-vulnerability-that-may-impact-hundreds-of-online-services) pelo laboratório SALT. Esta postagem específica destaca a vulnerabilidade descoberta no [Expo] (https://expo.dev/), um framework amplamente usado para implementar OAuth e outras funcionalidades. Ele aborda especificamente uma vulnerabilidade na biblioteca expo-auth-session, que já foi devidamente resolvida.
Se você tem interesse em OAuth ou está trabalhando num produto CIAM como nós, recomendamos fortemente que você leia este artigo. É bastante inspirador e fornece ideias úteis. Esses relatórios white-hat servem como um lembrete de como até mesmo a característica mais simples pode causar vulnerabilidades. Quando se trata de segurança cibernética e autorização, nunca podemos ser demasiado cuidadosos em garantir a segurança e privacidade das informações do usuário. Se este artigo chamar a sua atenção, acredito que você concordará fortemente conosco.
Lembrei-me do tempo em que começamos. Passamos muito tempo aprendendo e pesquisando os detalhes dos protocolos OAuth e OIDC. Foi doloroso e tedioso, mas os benefícios foram imensos. Embora talvez nem todos os indivíduos em nossa equipe sejam especialistas em OAuth, todos estão comprometidos em dedicar um esforço contínuo à segurança e meticulosidade. Com esses esforços dedicados, o produto Logto se transformou no que é hoje.
Graças a essa grande oportunidade, gostaríamos de relembrar alguns dos detalhes de segurança do OAuth aqui.
Uma visão geral do Fluxo de Autorização OAuth
[OAuth 2.0] (https://datatracker.ietf.org/doc/html/rfc6749#section-1.3.1) oferece vários fluxos de autorização de acordo com diferentes tipos de clientes e requisitos. Estes incluem o [Fluxo Implícito] (https://datatracker.ietf.org/doc/html/rfc6749#section-4.2), Fluxo de Credenciais do Cliente, [Fluxo de Credenciais de Senha do Proprietário do Recurso] (https://datatracker.ietf.org/doc/html/rfc6749#section-4.3) e Fluxo de Autorização do Dispositivo. No entanto, o Fluxo de Código de Autorização se destaca como o mais seguro e amplamente utilizado. Ao contrário dos outros fluxos, ele separa a autenticação do usuário da aplicação do cliente e envolve a troca de um Código de Autorização por tokens. Esta abordagem proporciona uma camada adicional de segurança, pois os tokens sensíveis nunca são expostos ao cliente. Além disso, o Fluxo de Código de Autorização suporta a gestão de tokens do lado do servidor, tornando-o adequado para aplicações web que requerem robustez de segurança e maior controle sobre o acesso do usuário.
Aqui está um diagrama mais simples do [Fluxo de Código de Autorização] (https://datatracker.ietf.org/doc/html/rfc6749#section-1.3.1):
Vamos dar uma olhada nas duas solicitações mais cruciais feitas no fluxo de concessão do Código de Autorização e nos fragmentos aparentemente triviais dentro delas, mas que desempenham um papel crucial na proteção contra fraudes.
O ponto final de autorização:
O ponto final da troca de token:
Credenciais do Cliente
No OAuth, [Credenciais do Cliente] (https://datatracker.ietf.org/doc/html/rfc6749#section-1.3.4) referem-se às credenciais usadas por um aplicativo cliente para autenticar e identificar-se perante o servidor de autorização. Essas credenciais são obtidas durante o processo de registro do cliente e são usadas para validar a identidade do cliente ao fazer solicitações ao servidor de autorização. (Você pode encontrar sua credencial de cliente no console de Admin do Logto quando você tiver seu aplicativo registrado pela primeira vez.)
As credenciais do cliente são tipicamente compostas por dois componentes:
- ID do Cliente : Um identificador único atribuído ao aplicativo cliente pelo servidor de autorização. É um valor público que geralmente não é considerado sensível.
- Segredo do Cliente : Um valor confidencial e armazenado de forma segura conhecido somente pelo cliente e pelo servidor de autorização. Serve como uma forma de autenticação para o aplicativo cliente e é usado para verificar a identidade do cliente ao fazer solicitações ao servidor de autorização.
Como você pode ver, a combinação de ID do Cliente e Segredo do Cliente é usada durante a solicitação do token para autenticar o cliente e obter Tokens de Acesso.
As credenciais do cliente desempenham um papel vital na garantia da segurança do fluxo OAuth. Eles ajudam o servidor de autorização a verificar a autenticidade dos aplicativos cliente e a controlar o acesso a recursos protegidos. É importante manusear as credenciais do cliente de maneira segura e protegê-las de acesso não autorizado. O Logto categoriza os aplicativos cliente em dois diferentes níveis de segurança:
- Clientes confidenciais: Incluem aplicações web renderizadas no servidor e aplicações máquina-a-máquina (M2M). No caso de clientes confidenciais, todas as credenciais relacionadas à autorização, incluindo credenciais do cliente, são armazenadas de forma segura no lado do servidor. Além disso, todas as solicitações de troca intermediária são criptografadas para garantir a confidencialidade dos dados. O risco de vazamento de credenciais do cliente para clientes confidenciais é muito baixo, tornando-os inerentemente mais seguros. Portanto, os clientes confidenciais são tratados com um nível de segurança maior por padrão. No fluxo de troca de token, apresentar o Segredo do Cliente é OBRIGATÓRIO.
- Clientes públicos: Incluem aplicações web de uma única página (SPA) e aplicações nativas. Para clientes públicos, as credenciais do cliente são tipicamente codificadas no lado do cliente, como em um pacote JavaScript ou um pacote de aplicativo em uma plataforma nativa. O risco de vazamento de credenciais é maior quando comparado com clientes confidenciais, devido à exposição inerente das credenciais do cliente no código do lado do cliente. No fluxo de troca de token, apresentar o Segredo do Cliente é OPCIONAL. O Logto não confia nessas credenciais de um cliente público por padrão.
Estado
No fluxo OAuth, o parâmetro state
é um valor gerado aleatoriamente que é incluído na solicitação de autorização enviada pelo cliente ao servidor de autorização. Sua finalidade é manter o estado ou contexto da solicitação do cliente ao longo do processo de autorização.
O parâmetro state
atua como uma medida de segurança para prevenir ataques de falsificação de solicitação entre sites (CSRF). Quando o servidor de autorização redireciona o usuário de volta para o aplicativo cliente após autenticação e autorização, ele inclui o mesmo valor de estado na resposta. O aplicativo cliente DEVE
comparar este valor com o valor state
original que enviou na solicitação de autorização.
Verificando o parâmetro state, o cliente pode garantir que a resposta recebida do servidor de autorização corresponde à solicitação inicial que fez. Isso ajuda a prevenir ataques onde um atacante tenta enganar o cliente para aceitar uma resposta destinada a outro usuário ou aplicativo.
Considere o seguinte exemplo de ataque CSRF num caso de uso fictício:
Ataque CSRF: Fraude para vincular conta social - problema
Com um mecanismo de validação de estado adequado, o cliente pode detectar o ataque e evitar que o usuário seja redirecionado para o site do invasor:
Ataque CSRF: Fraude para vincular conta social - solução
PKCE
Como mencionado anteriormente, clientes públicos como aplicações web SPA e aplicações nativas apresentam um risco maior de vazamento de credenciais de autenticação, incluindo o Código de Autorização emitido pelo servidor de autorização.
PKCE significa [Proof Key for Code Exchange] (https://datatracker.ietf.org/doc/html/rfc7636). Trata-se de uma extensão para o [Authorization Code Flow] (https://datatracker.ietf.org/doc/html/rfc6749#section-1.3.1) do OAuth 2.0 que melhora a segurança dos clientes públicos.
O PKCE foi introduzido para mitigar o risco de um atacante interceptar o Código de Autorização e trocá-lo por um Token de Acesso sem o conhecimento do cliente. Este tipo de ataque, conhecido como ataque de interceptação de Código de Autorização, é mais prevalente em ambientes onde o aplicativo cliente não pode armazenar de forma segura um segredo de cliente.
Para implementar PKCE, o aplicativo cliente gera um Verificador de Código aleatório e deriva um Desafio de Código a partir dele usando um algoritmo de hashing específico (geralmente SHA-256). O Desafio de Código é incluído na solicitação de autorização inicial enviada ao servidor de autorização.
Quando o servidor de autorização emite o Código de Autorização, o aplicativo cliente inclui o Verificador de Código original na solicitação de token. O servidor verifica se o Verificador de Código corresponde ao Desafio de Código armazenado e somente então emite o Token de Acesso.
Usando PKCE, o aplicativo cliente garante que o Código de Autorização sozinho não é suficiente para obter um Token de Acesso. Este mecanismo adiciona uma camada extra de segurança ao fluxo de autorização, especialmente para clientes públicos onde o armazenamento de Segredos de Cliente é desafiador.
Logto usa PKCE como o ÚNICO fluxo de autorização para todos os aplicativos de tipo de cliente público. No entanto, PKCE pode ser omitido para aqueles clientes confidenciais.
URI de Redirecionamento
Um [Redirect URI (Uniform Resource Identifier)] (https://datatracker.ietf.org/doc/html/rfc6749#section-3.1.2) é um ponto final específico ou URL para o qual o servidor de autorização redireciona o usuário após o processo de autenticação e autorização em OAuth.
Durante o fluxo OAuth, o aplicativo cliente inclui um Redirect URI como parte da solicitação de autorização inicial. Este URI serve como o URL de retorno de chamada para onde o usuário será redirecionado após autenticar e conceder permissões para o cliente.
Assim que o usuário completa o processo de autenticação, o servidor de autorização gera uma resposta que inclui um Código de Autorização e redireciona o usuário de volta para o Redirect URI especificado.
A validação do Redirect URI é uma etapa essencial para assegurar a segurança e integridade do fluxo OAuth. Ela envolve a verificação de que o Redirect URI usado na solicitação de autorização e nos redirecionamentos subsequentes é válido e confiável.
Vamos voltar e dar uma olhada no relatório de vulnerabilidade OAuth original (https://salt.security/blog/a-new-oauth-vulnerability-that-may-impact-hundreds-of-online-services). (A seguinte seção é referenciada do post original)
Quando o usuário clica em “login com facebook” usando o APP móvel no Expo Go, ele redireciona o usuário para o seguinte link:
https://auth.expo.io/@moreisless3/me321/start?authUrl=https://www.facebook.com/v6.0/dialog/oauth?code_challenge=...&display=popup&auth_nonce=...&code_challenge_method=S256&redirect_uri=https://auth.expo.io/@moreisless3/me321&client_id=3287341734837076&response_type=code,token&state=gBpzi0quEg&scope=public_profile,email&returnUrl=exp://192.168.14.41:19000/--/expo-auth-session
Na resposta, auth.expo.io definiu o seguinte cookie: ru=exp://192.168.14.41:19000/--/expo-auth-session. O valor RU será usado posteriormente como Return Url na etapa 5. Ele então mostra ao usuário uma mensagem de confirmação, e se o usuário aprovar - ele o redireciona para o login do Facebook para continuar o fluxo de autenticação
…
Esta página lê o parâmetro de consulta “returnUrl” e o ajusta o cookie de acordo.
Vamos mudar o returnUrl para
hTTps://attacker.com
(https não é permitido, então tentei inserir letras maiúsculas e funcionou), que define o RU (Return Url) no cookie parahttps://attacker.com
.…
No caso acima, descarte dos parâmetros redirect_uri
originais, o Expo introduziu um novo parâmetro chamado returnUrl sem validação adequada. Esta supervisão proporcionou uma oportunidade para atacantes obterem acesso ao Código de Autorização retornado pelo Facebook. Para mais detalhes, por favor, consulte o post original.
A validação do Redirect URI serve a vários propósitos importantes:
- Prevenir ataques de phishing: Ao validar o Redirect URI, o servidor de autorização garante que o usuário seja redirecionado de volta para um ponto final confiável e autorizado. Isso ajuda a prevenir que atacantes redirecionem usuários para localidades maliciosas ou não autorizadas.
- Protegendo contra redirecionamentos abertos: Redirecionamentos abertos são vulnerabilidades que podem ser exploradas para redirecionar usuários para sites maliciosos. Ao validar o Redirect URI, o servidor de autorização pode assegurar que o redirecionamento permaneça dentro das fronteiras do domínio autorizado ou do conjunto de domínios confiáveis.
- Garantindo o roteamento correto das respostas de autorização: Validar o Redirect URI ajuda a garantir que o servidor de autorização redirecione o usuário de volta ao aplicativo cliente pretendido. Ele garante que a resposta, como um Código de Autorização ou Token de Acesso, seja entregue ao destino correto.
No Logto, o registro redirect_uri
é obrigatório para todos os tipos de aplicativos. Nós comparamos e combinamos o valor recebido com os registrados no servidor Logto. Isso inclui quaisquer parâmetros de pesquisa personalizados. Se um pedido de autorização falhar na validação devido a um valor redirect_uri
faltante, inválido ou não correspondente, um erro de Redirect URI inválido será retornado ao redirect_uri
registrado no arquivo.
Resumo
Devido à sua natureza intrincada e sutil, é compreensível que esses detalhes sejam frequentemente negligenciados. Alguns são apenas uma string aleatória como state
.
No entanto, é importante notar que essas medidas de segurança adicionam camadas de proteção à autorização do usuário, mitigando riscos como ataques CSRF, interceptação de Código de Autorização e redirecionamentos não autorizados.
Estes são apenas uma pequena parte das características abrangentes de segurança oferecidas pelo protocolo OAuth. OAuth oferece um framework robusto para autenticação segura e autorização. Ele também oferece pontos finais flexíveis e abertos para atender a vários requisitos em aplicações de produtos do mundo real.
Como desenvolvedores e provedores de serviços, é imperativo priorizar continuamente a segurança do fluxo de autorização do usuário. Manter-se vigilante, aderir às melhores práticas e manter-se atualizado com os desenvolvimentos mais recentes no ecossistema OAuth são essenciais para assegurar a integridade e proteção das identidades do usuário e dados sensíveis. Nós continuaremos comprometidos em manter os mais altos padrões de segurança na implementação do OAuth e na proteção da privacidade e confiança de nossos usuários.