1 pontos por GN⁺ 2023-10-23 | 1 comentários | Compartilhar no WhatsApp
  • No fluxo de conexão OAuth do Outlook Calendar no Harvest, a URL de callback redirecionava novamente para o destino do valor state, causando um redirecionamento aberto; combinado com o fluxo de concessão implícita, isso podia expor o token a uma URL externa
  • O problema não estava na Microsoft, mas sim na integração do Harvest, onde o redirect_uri OAuth registrado acabava funcionando como um intermediário de redirecionamento que enviava o usuário para um domínio definido pelo atacante
  • O state é um JSON codificado em URI, e ao inserir um domínio externo com barra em subdomain, como example.com/, o redirecionamento passava a ir para algo como example.com/.harvestapp.com/...
  • A PoC mostra um fluxo em que a URL de autorização OAuth da Microsoft usa client_id=0dcef4db-36d8-4aed-9cc5-ab43e1814884, response_type=id_token, response_mode=fragment e scope=openid, fazendo com que o fragmento #id_token=... seja anexado ao destino do redirecionamento
  • A vulnerabilidade foi reportada em 23 de agosto de 2020, teve o patch confirmado em 1º de agosto de 2023, e em 22 de outubro de 2023 a Harvest pediu desculpas dizendo que o atraso foi um human error

Como o token vazava no callback OAuth

  • O Harvest é um software de rastreamento de tempo que permite ao usuário conectar o Outlook Calendar via OAuth
  • Quando a autorização era bem-sucedida, o usuário era redirecionado para https://outlook-integration.harvestapp.com/auth/outlook-calendar/…
  • Esse callback então redirecionava o usuário novamente para a URL fornecida dentro de state, e nesse processo ocorria o redirecionamento aberto
  • O valor state observado originalmente na URL de callback era um JSON codificado em URI
    • Ao decodificar, fica no formato {"return_to":"/","subdomain":"hackerone295"}
    • O valor de subdomain é usado para inferir um espaço do app Harvest, como hackerone295.harvestapp.com
  • Se fosse adicionada uma barra a subdomain, como em example.com/, a URL de callback passava a redirecionar para um domínio externo
  • Como essa URL de callback era o redirect_uri registrado no aplicativo OAuth, combinar o redirecionamento aberto com o fluxo de concessão implícita podia expor o token ao destino do redirecionamento
  • A URL de autorização usada na PoC tinha os seguintes valores
  • No fim, o usuário era redirecionado para algo no seguinte formato
  • Não se tratava de uma vulnerabilidade da Microsoft

Tempo entre o reporte e o patch

  • A equipe do Harvest respondeu muito pouco durante o processo de divulgação e correção da vulnerabilidade, e mesmo após reconhecê-la na triagem, a correção demorou bastante
  • A vulnerabilidade foi reportada em 23 de agosto de 2020, e o Harvest fez o primeiro contato em 16 de outubro de 2020
  • Em 27 de novembro de 2020, o relatório passou ao estado triaged
  • Em 28 de abril de 2022, a empresa disse que estava corrigindo o problema e estimou 2 semanas, mas a correção real levou cerca de mais 1 ano
  • Em 1º de agosto de 2023, foi confirmado que a vulnerabilidade havia sido corrigida
  • Em 21 de outubro de 2023, o relatório foi tornado público por meio de uma postagem
  • Na mesma data, o relatório ainda estava em estado de triagem, e embora a política de bug bounty mencionasse recompensa, nenhum bounty nem pontos no HackerOne foram pagos
  • Em 22 de outubro de 2023, depois que a postagem ganhou atenção, a Harvest explicou e pediu desculpas dizendo que foi um human error

1 comentários

 
GN⁺ 2023-10-23
Opiniões no Hacker News
  • Como responsável pelo programa de bug bounty, vou explicar o que aconteceu internamente. Já pedi desculpas a @0xcrypto e expliquei internamente, mas acho correto resumir aqui também.
    Desde o início, não consegui reproduzir completamente o problema e também não podia encerrá-lo por medo de estar deixando passar algo. Logo depois da minha última resposta dizendo que “encontraria uma solução”, eu estava me aproximando da conclusão de que não era reproduzível e, com a chegada de uma denúncia relacionada a OAuth parecida, houve confusão interna e achei, por engano, que já havíamos tratado e comunicado o caso.
    Por causa das configurações de notificação, perdi as mensagens de acompanhamento, e a issue ficou indefinidamente no estado Triage, sem atualizações. Isso não é uma desculpa; como alguém que atuou por muito tempo como bug bounty hunter, sei muito bem como é frustrante esperar atualizações de uma empresa. A segurança dos clientes é prioridade máxima, e o que está escrito na página de segurança é verdade.

    • Erros podem acontecer, mas ainda não foi explicado o fato de que, mesmo tendo contatado a HackerOne várias vezes ao longo de 3 anos, a HackerOne não conseguiu falar com a Harvest.
      Além disso, agora também não está claro como será tratada uma denúncia que não pode mais ser reproduzida. Eu queria discutir mais na HackerOne, mas depois da mensagem de desculpas parece que voltou a haver falta de resposta.
    • Tenho curiosidade de saber se, no fim das contas, vocês acreditam que a vulnerabilidade realmente funcionava da forma descrita e, se sim, por que falharam em reproduzi-la.
    • É bom poder ouvir uma explicação direta. Mesmo que não tenha sido reproduzido, fico pensando se não teria sido fácil verificar pelo código-fonte se um open redirect era possível.
    • Pelo menos é bom ver que foi publicado um texto dizendo que estão levando isso a sério. Qualquer um pode cometer erros, mas acho que as coisas crescem quando, depois de um erro, ninguém assume a responsabilidade.
    • Uso bastante o Harvest, mas gostaria que agora também consertassem o novo app móvel para iOS. Surgiram tantos probleminhas que até parei de reportá-los ao suporte.
      O estado do app frequentemente diverge do estado do servidor; mudanças no servidor só aparecem depois de uma atualização forçada, ou mudanças feitas no cliente são revertidas após salvar. A experiência de rastreamento de tempo também é inconveniente: às vezes é preciso rolar para ver o botão, ou a posição dos botões de iniciar/parar/reiniciar/excluir muda constantemente conforme o estado do item. O app antigo não era bonito, mas funcionava sem problemas.
  • É bem preocupante. Quando usei o Harvest, o suporte era realmente excelente: respondia rápido, entendia em detalhes como os clientes usavam o produto e também explicava com cuidado maneiras criativas de aproveitar funcionalidades existentes.
    Para recursos não implementados, a resposta era “vamos colocar no backlog, mas não podemos garantir”. Consta que há 30 pessoas na engenharia [1], mas não sei bem onde esse pessoal está sendo usado, porque também não vi outros recursos saindo rapidamente.
    Comecei a receber spam como “usuário do Harvest” e suspeitei que tivessem vendido a lista de clientes; os responsáveis da empresa entraram em contato imediatamente, negaram enfaticamente e trataram o assunto com seriedade suficiente para investigar na hora. Isso foi bom.
    Mas, no fim, isto também parece um problema de engenharia. Descobri uma forma bastante fácil de estimar clientes ativos, e isso também entrou no “backlog” e não foi corrigido por meses. A correção parecia muito trivial. Além disso, MFA só é oferecido ao fazer login com o Google [2]. Ainda assim, o app em si faz muito bem o que se propõe a fazer.
    1: https://www.getharvest.com/about/meet-the-team
    2: https://support.getharvest.com/hc/en-us/articles/36005266713...

    • Obrigado pela avaliação positiva. Concordo plenamente que a equipe de suporte é excelente. É uma equipe pequena, mas trata todos os assuntos com muita seriedade e participou diretamente da investigação mencionada.
      A falha de comunicação com o autor da denúncia neste thread foi inteiramente minha, e, como expliquei na resposta no topo, vou garantir que isso não aconteça novamente.
    • Não sei se você gosta ou não. É sarcasmo?
    • A qualidade do suporte foi realmente boa. As solicitações sempre eram tratadas por pessoas muito competentes, e normalmente eu recebia resposta em poucos minutos.
      Alguns dos pedidos de recursos acabaram entrando de fato no produto. Talvez não tenha sido por minha influência, mas pelo menos parecia que tínhamos ideias parecidas sobre um bom rastreador de tempo.
  • O título parece bastante injusto com a Microsoft. Dá a impressão de estar se aproveitando da atenção recente sobre incidentes de autenticação da Microsoft; assim que vi o título, pensei “mais uma invasão na MS?”.
    Na prática, eram tokens da Harvest, e, por causa de uma vulnerabilidade de injeção no código da Harvest, apenas as permissões de acesso ao app Harvest foram expostas indevidamente. Teria sido igualmente vulnerável por trás de qualquer outro provedor de identidade.

    • Sou o autor do post no blog. Entendo a preocupação e tentei tirar o nome da Microsoft do título, mas não consegui pensar em uma formulação adequada.
      Isso porque a vulnerabilidade afeta apenas a implementação OAuth para conexão com contas Microsoft. O título original era “Microsoft OAuth token leak via open redirect in Harvest App” e depois mudei para “Microsoft Account's OAuth tokens leaking via open redirect in Harvest App”. Ainda penso em alterá-lo e aceito sugestões.
    • Pensei a mesma coisa. Cheguei até a me perguntar se o texto realmente entende como o OAuth funciona e, mesmo assim, chama isso de token da MS.
  • A RFC 6749 aborda em detalhes como o servidor de autorização deve impedir esse tipo de ataque.
    O servidor de autorização deve exigir obrigatoriamente o registro de URI de redirecionamento para clientes públicos, e é recomendável exigir também para clientes confidenciais. Quando uma URI de redirecionamento é fornecida na solicitação, o servidor de autorização deve validá-la comparando-a com o valor registrado.
    Então fico curioso: o app Harvest não teria registrado um redirect_uri malicioso; como isso foi possível? Será que o servidor OAuth da Microsoft ignora os parâmetros de URL dentro do redirect_uri ao compará-lo com as URIs de redirecionamento registradas do cliente OAuth?

    • Parece que colocaram um segundo redirecionamento por cima e o inseriram no parâmetro state. Provavelmente a intenção era redirecionar para qualquer lugar.
      O fluxo pretendido seria: ir para a URL de autenticação do Harvest → redirecionar para a URL de autenticação da Microsoft com redirect_uri=registered_uri e state=some_encoded_final_uri → o usuário inserir as credenciais → redirecionar para a URI registrada → ler o state e redirecionar novamente para a URI contida nele.
      Esse ataque ainda redireciona para uma URI permitida, mas esse endpoint lê o state e repassa a resposta/o token sem alterações. Foram três erros: uso indevido de state, não criptografar nem validar o state se ele fosse ser usado dessa forma, e ter ativado a concessão implícita. Se isso fosse necessário, deveriam ter criado um registro separado para um uso limitado.
    • O redirect_uri do Harvest está registrado na Microsoft. Depois que o servidor OAuth da Microsoft redirecionou para o Harvest, o Harvest implementou seu próprio redirecionamento com base nos dados em state.
  • A concessão implícita é bem terrível por motivos como os mostrados neste texto.
    Aliás, ela será removida da especificação OAuth 2.1 que está por vir: https://www.ietf.org/archive/id/draft-ietf-oauth-v2-1-09.htm...

    • Ela já não estava marcada para descontinuação há uns 6 anos? CORS substituiu esse uso, então não há motivo para mantê-la na nova especificação.
  • Quer dizer que levou 3 anos para corrigir a vulnerabilidade? De agosto de 2020 a agosto de 2023; não sei o tamanho da equipe do Harvest, mas ainda assim parece absurdo.

    • Como é comum em muitas empresas, provavelmente entrou no backlog com baixa prioridade, passou por algumas reorganizações do Jira e reestruturações organizacionais e acabou sendo descoberto e corrigido depois.
    • Sou da equipe de segurança do Harvest. Como respondi em outro comentário, basicamente não conseguimos reproduzir e não houve uma correção explícita. O problema é que um ticket que deveria ter sido fechado ficou em estado de Triage por erro humano meu.
  • Gostaria que algum especialista em OAuth explicasse esse problema com um pouco mais de detalhe. Li o blog algumas vezes, mas ainda não entendi a vulnerabilidade em si.
    Pelo pouco que sei de OAuth, o app Harvest pede à Microsoft para verificar o usuário, a Microsoft verifica o usuário e, se der certo, redireciona para a URL de callback passando o token de acesso no corpo da resposta, não é assim?
    Nesse caso, o autor do blog não apenas criou uma URL artesanal que fazia a URL de retorno ir para example.com em vez da URL de retorno real?

    • Sim. O autor do blog criou esse tipo de URL artesanal. Só que a URL de callback na URL de ataque é do domínio harvestapp, e a parte controlada pelo atacante fica dentro de state, que é praticamente opaco do ponto de vista do servidor OAuth.
      Com essa URL, é possível enviar a alguém um link de login.microsoftonline.com, mostrar um prompt de login dizendo “entrar no Harvest” e então o atacante obter permissões relacionadas à conta real do Harvest.
      Normalmente isso seria impossível. O atacante até poderia registrar um novo app que redireciona para example.com, mas isso seria inútil, porque ele não obteria um token de acesso com permissões relacionadas ao Harvest.
      O app OAuth do lado da Microsoft tem uma lista de redirecionamentos válidos permitidos, então uma tentativa como login.microsoftonline.com/authorize?client_id=$harvestAppID&redirect_uri=attacker.com gera erro do lado da Microsoft. O ataque é possível porque uma URL válida de outlook-integration.harvestapp.com recebe o token de acesso e depois redireciona novamente para o site do atacante, levando também o token de acesso.
    • A vulnerabilidade veio de outlook-integration.harvestapp.com. Depois que o callback OAuth2 tinha sucesso, eles usavam como state um objeto JSON com instruções do que executar.
      A propriedade subdomain era usada para redirecionar o navegador para um subdomínio de harvestapp.com passando #id-token. O problema é que o valor de subdomain era injetado diretamente na URL abaixo:
      https://${subdomain}.harvestapp.com/...#id-token=...
      Se, no payload JSON, subdomain fosse definido como um valor com barra no fim, como attacker-controlled.com/, a URL viraria https://attacker-controlled.com/.harvestapp.com/...#id-token=.., e o navegador iria para outro domínio, vazando o token.
    • A Microsoft verifica se a URL de retorno está na lista permitida especificada pelo Harvest. O Harvest provavelmente adicionou um mecanismo próprio de redirecionamento por cima disso para dar suporte a várias instâncias do software, mas não sanitizou corretamente o valor de entrada do redirecionamento.
      Portanto, não é um problema implícito do OAuth em si, e sim uma implementação ruim.
    • Não sei exatamente, mas acho que o problema foi o Harvest ter permitido todas as URLs como URL de callback. Eles deveriam informar à Microsoft que apenas URLs específicas podem ser usadas como callback.
      Ao configurar o workflow, em vez de criar uma lista real de URLs de callback confiáveis, é possível que tenham usado um curinga na lista de callbacks permitidos. Posso estar totalmente errado.
  • Não entendo por que esperaram 3 anos. Um período de carência antes da divulgação de 90 dias é suficiente

    • Se for necessária uma mudança enorme e uma equipe relativamente grande dedicar a maior parte do tempo de trabalho a esse problema, pode levar mais de 90 dias. Ou pode até haver uma solução, mas, por causa da notificação aos clientes, talvez seja preciso seguir um cronograma específico e relativamente curto
      Ainda assim, essa prorrogação do prazo deve ser algo permitido pelo pesquisador ou por seu advogado/representante. É o tipo de coisa que uma empresa pode pedir de boa-fé em casos maiores que o normal
  • Se a HackerOne deixa as empresas engavetarem esse tipo de coisa por 3 anos, parece que não está fazendo seu papel direito

    • A HackerOne depende das empresas que operam programas de bug bounty. O grau de envolvimento varia muito conforme os serviços oferecidos, por exemplo se há triagem ou não
      No nível mais básico, ela apenas fornece uma plataforma de divulgação de vulnerabilidades e um texto jurídico padrão para evitar que o pesquisador seja processado pelo departamento jurídico
      Na maioria dos casos, as empresas rejeitam pedidos de divulgação. Se o pesquisador divulgar sem permissão, viola os acordos com a HackerOne e com a empresa e fica exposto a responsabilidade legal. Neste caso, parece que a empresa concordou com a divulgação e, mesmo que a resposta tenha sido muito lenta, acho que isso merece reconhecimento
      Pessoalmente, também já tive várias vezes bugs com recompensas na casa dos quatro dígitos que ficaram mais de um ano sem correção, mas não achei que fosse culpa da HackerOne
    • Já lidei, pelo lado da empresa, com issues na HackerOne, e um participante da HackerOne continuava violando as próprias regras da HackerOne. Houve descumprimento de cronograma de divulgação, publicações falsas sobre o bug em redes sociais e até ameaças a funcionários
      A HackerOne não se importou. Mesmo após avisarmos várias vezes que aquela pessoa estava violando as regras deles, disseram que não podiam fazer nada
      A impressão era de uma empresa que tinha sido reduzida a uma equipe mínima depois de já estar operacional, com atendentes de suporte sem autoridade respondendo perguntas. Isso foi há bastante tempo, então talvez hoje seja diferente, mas essa foi a impressão na época
    • Entre as três partes — HackerOne, a empresa e o pesquisador que encontrou o bug — é a empresa que detém toda a alavancagem
      Se as empresas sentirem que a HackerOne está passando dos limites e decidindo o que vai “permitir” que a empresa faça, elas simplesmente deixarão a HackerOne e criarão uma solução interna
    • Talvez seja necessário ter avaliações de empresas, para evitar empresas ruins que deixam casos se arrastarem por anos e nem pagam recompensa
  • Não entendo por que esse problema não foi encaminhado à Microsoft. A Microsoft poderia ter revogado o acesso desse aplicativo OAuth até que o problema fosse corrigido
    Ainda assim, imagino que existam milhares de implementações igualmente ruins conectadas à Microsoft via OAuth

    • Eu não sabia que isso era possível. Pessoalmente, acho que jamais teria pensado nisso