Por Gabrielle Delgado

Para quem não lembra, eu me chamo Gabrielle e já fiz um outro blogpost aqui no SideChannel falando um pouco sobre minha experiência de estágio e sobre um plugin do Burp para detectar o reverse tabnabbing. De lá pra cá eu tive meu contrato de estágio renovado e passei 6 meses me aprofundando ainda mais em segurança de aplicações web, mobile e advanced penetration testing. Da mesma forma que ocorreu no primeiro estágio, meus tutores me instruíram a pesquisar e fazer uma publicação para o fechamento do meu estágio. Foi daí que surgiu este blogpost.

A propósito, ao final do meu segundo ciclo de estágio a Tempest me fez uma oferta de emprego e eu, claro, aceitei na hora! Isso significa que eu sou a primeira funcionária do time de Consultoria da Tempest. 😀

Sem mais delongas, vamos ao que interessa!

Para muitos usuários da internet, os navegadores (browsers) tornaram-se uma peça fundamental no nosso dia a dia. Os aplicativos de utilidade de escritórios, como por exemplo o Microsoft Office 365, rodam na nuvem e são acessíveis por meio de um browser. Podemos trabalhar a qualquer hora, qualquer lugar, no celular, tablet ou laptop. Em alguns casos, os usuários não precisam instalar nenhum componente adicional para acessar tais aplicações ou dados corporativos, portanto menos trabalho para nós de TI! Mas será mesmo?

Essa evolução de tecnologias abriu caminho para ótimas experiências aos usuários finais, mas também deu aos agentes maliciosos novos meios, endpoints e vulnerabilidades a serem exploradas em possíveis ataques. A partir disso, neste blog post estaremos tratando especificamente sobre uma análise em cinco navegadores que são utilizados em dispositivos móveis, são eles: Google Chrome, Microsoft Edge, Opera, Samsung Internet Browser e Mint Browser. Para uma melhor visualização do escopo dessa pesquisa, vejamos a tabela a seguir:

Trouxemos um gráfico de Janeiro de 2019 até Março de 2020, dos navegadores móveis mais utilizados mundialmente, para mostrar que uma exploração de algum problema de segurança em um browser pode ter um grande impacto:

Figura 1 — Gráfico com os navegadores mais utilizados mundialmente (Fonte gs.statcounter.com)

A análise nesta pesquisa tem como objetivo averiguar a maturidade de segurança dos navegadores mencionados previamente, navegadores populares e que já vêm pré-instalados em dispositivos Android (citados na Tabela 1), para avaliar as proteções fundamentais e ataques que poderiam facilmente obter sucesso.

Problemas de segurança

Para esta pesquisa foram selecionados quatro tipos de problemas de segurança, são eles: a possibilidade de bypass do Same Origin Policy, bypass do Content Security Policy, o ataque Scroll Jail e a investida de history.back() Open Redirect. Em seguida será apresentada uma breve descrição de cada um dos testes que foram efetuados nos navegadores alvos.

Same Origin Policy Bypass

O Same Origin Policy (SOP) é um mecanismo de segurança que restringe como um documento ou script pertencente a uma origem pode interagir com o conteúdo de outra fonte. Isso ajuda a isolar potenciais documentos maliciosos e reduzir vetores de ataque.

O primeiro teste realizado foi a tentativa de burlar essa proteção, utilizando scripts e, a partir de uma origem X, acessar recursos de uma origem Y. Segue abaixo um exemplo de script utilizado:

Figura 2 — Exemplo da tentativa de burlar o SOP

Nenhum dos browsers citados neste trabalho executou o console.log, logo podemos presumir que eles estão protegidos contra o método descrito acima.

Além do exemplo anterior, foi realizado um teste para verificar o comportamento dos browsers em se tratando do Cross Origin Resource Sharing (CORS), que é um mecanismo em que os browsers habilitam o acesso controlado a recursos localizados fora de um determinado domínio, adicionando campos no cabeçalho HTTP que permitem que os servidores definam um conjunto de origens que possuem permissão para ler uma informação usando o browser.

Em outras palavras, ele estende e adiciona uma flexibilidade à política de mesma origem (Same Origin Policy). Ainda, para requisições HTTP que podem causar efeitos colaterais nos dados do servidor (métodos HTTP diferentes de GET ou para uso de POST com certos MIME types) é necessário que os navegadores “pré-enviem” uma requisição solicitando os métodos suportados pelo servidor, isso é feito utilizando o método HTTP OPTIONS e, após a “aprovação”, o servidor envia a requisição verdadeira com o método HTTP correto; essas requisições “pré-enviadas” são chamadas de Preflight requests.

Entendido como funciona o CORS na teoria, vamos ver na prática: A requisição OPTIONS utiliza três campos no cabeçalho de solicitação HTTP, que são o Access-Control-Request-Method,Access-Control-Request-Headers, e o campo Origin. Se o servidor permitir, ele responderá à requisição preflight com um campo de cabeçalho de resposta Access-Control-Allow-Methods, que lista os métodos permitidos pelo servidor, além do Access-Control-Allow-Origin que indica se os recursos da resposta podem ser compartilhados com a origem dada (Origin).

Segue o exemplo onde o domínio https://c3415fa3.ngrok.io solicita uma requisição POST de um outro domínio, https://usus.serveo.net:

Figura 2.2 — Exemplo da requisição cross-domain

Com essa requisição POST, uma Preflight request é gerada:


Figura 2.3 — Preflight request gerada
Figura 2.4 — Configuração do servidor

Como podemos ver na imagem anterior (figura 2.4), o campo Access-Control-Allow-Origin foi configurado no servidor com o wildcard “*”, em tese, permitindo qualquer origem. Contudo, para os casos de utilização de credenciais (representadas pelo uso de cookies, por exemplo), os browsers de mercado deveriam bloquear o acesso ao recurso, visto que tal conduta é bastante perigosa, podendo potencializar ataques clássicos como Cross-Site Request Forgery.

Sabendo disso, o teste realizado foi justamente para verificar se todos os browsers bloqueiam o acesso a recursos cross-origin nesse cenário, e felizmente todos os browsers contidos na pesquisa possuem esse critério.

Como prova de conceito, caso seja permitido o acesso cross-origin, o alert(xhr.response) contido na figura 2.2 deve printar a linha 27 da figura 2.4 (contendo o texto Hello world!).

Considerando nosso teste com o wildcard *, o resultado pode ser visto na figura 2.5, a seguir:

Figura 2.5 — Alerta no browser Opera com campo Access-Control-Allow-Origin: *

Como podemos ver na imagem anterior (figura 2.5), o response contendo o texto Hello world! não foi exibido.

Consideremos agora o cenário em que o campo Access-Control-Allow-Origin reflete a mesma origem do requisitante. Vejamos o resultado na figura 2.6, a seguir:

Figura 2.6 — Alerta no browser Opera com campo Access-Control-Allow-Origin: https://c3415fa3.ngrok.io (mesma origem do requisitante)

Como pode ser observado na figura 2.6, o response foi exibido no nosso alert pois, nesse cenário (com o campo Access-Control-Allow-Origin refletindo a mesma origem do requisitante), o acesso cross-origin é permitido pelo browser.

Content Security Policy Bypass

Content Security Policy ou CSP é um campo no cabeçalho de resposta HTTP que os browsers modernos utilizam para melhorar a segurança dos documentos ou páginas Web. O campo Content-Security-Policy permite que você restrinja recursos como JavaScript, CSS, entre outros. Ele pode, por exemplo, diminuir a superfície dos ataques de Cross Site Scripting e ClickJacking declarando quais recursos dinâmicos podem ser carregados.

Em resumo, as políticas instruem o browser a ter um comportamento de carregamento dos conteúdos a partir do que foi especificado no cabeçalho. Através do acesso ao site recomendado para o teste, o https://content-security-policy.com/browser-test/, foi possível confirmar que todos os navegadores escolhidos para essa pesquisa suportam e contém a política do CSP nos 3 níveis recomendados pela W3C (World Wide Web Consortium).

Em contrapartida, no navegador móvel Google Chrome, através de uma injeção de política, houve a sobrescrição da diretiva existente script-src. A partir da utilização da diretiva script-src-elem, foi possível sobrescrever diretivas script-src existentes. Através de uma prova de conceito criada por Gareth Heyes, pesquisador da PortSwigger, um XSS foi acionado sem qualquer dificuldade.

Prova de conceito:

http://portswigger-labs.net/edge_csp_injection_xndhfye721/?x=%3Bscript-src-elem+*&y=%3Cscript+src=%22http://subdomain1.portswigger-labs.net/xss/xss.js%22%3E%3C/script%3E

Código HTML:

Figura 3 — Código HTML

Código xss.js:

Figura 3.2 — Código do arquivo xss.js

Figura 3.3 — XSS executado no Chrome

Como podemos ver, na URL, é inserida a diretiva script-src-elem e incluída a tag script com o link para o arquivo malicioso. Com isso, o alert(document.domain) é executado.

history.back() Open Redirect

O método history.back() carrega a URL anterior na lista do histórico do navegador — é o mesmo que utilizar o botão “voltar” dos navegadores (o método history.go(-n) é uma segunda forma de fazer isso, sendo n o número de vezes que desejar voltar a página). Outros métodos que precisamos ter conhecimento são o history.replaceState(state, title[, url]), que permite modificar entradas no histórico do navegador, e o history.pushState(state, title[, url]), que registra uma nova entrada no seu histórico de sessão. Sabendo disso, vamos para o exemplo.

Os parâmetro state, title e url correspondem, respectivamente, a um objeto JavaScript associado à entrada de histórico criada, título da página e a URL que será modificada/registrada no histórico. Um ponto importante é que os browsers devem bloquear a execução desses métodos caso a nova URL não seja do mesmo domínio da URL atual. Vamos para o exemplo:

Primeiramente, temos uma página legítima A, que tem um link para uma página B maliciosa.

Figura 4 — Página A com o link para a página B

Quando a vítima acessa essa página B a partir da A e clica no link, o seguinte script é acionado:

Figura 4.2 — Página B contendo o método history.pushState().

Como podemos ver na Figura 4.2, ao clicarmos no “Click here” somos direcionados à página C:

Figura 4.3 — Conteúdo da página C

Na página C, ao usarmos a setinha para voltar uma página, devemos ser direcionados para o site que foi posto pelo history.replaceState(), nesse caso https://www.tempest.com.br.

Contudo, como dito anteriormente, os navegadores presentes na pesquisa bloquearam essa funcionalidade pois eles exigem que a URL nova seja do mesmo domínio da URL atual, como podemos ver a seguir:

Vídeo 1 — Demonstração do exemplo com com domínios distintos no Microsoft Edge

Vídeo 1.2 — Demonstração do exemplo com o mesmo domínio no Microsoft Edge

Esse exemplo foi motivado pelo artigo “Phishing with history.back() open redirect” (https://medium.com/@0xHyde/exploiting-history-back-3ec789c124dd), e nenhum dos navegadores citados nessa pesquisa realizaram a troca da URL.

Scroll Jail

Na grande maioria dos navegadores para celular, quando o usuário realiza um scroll da página, o navegador oculta a barra de URLs. Com isso, um site malicioso com o seu propósito de phishing pode usar esse comportamento para se apresentar como um site diferente, exibindo sua própria barra de URL falsa. Aí você deve estar pensando “Mas quando eu volto para o início da página a barra de URL volta a aparecer!”, porém, ainda assim, depois que o navegador ocultar a barra de URL, podemos mover todo o conteúdo da página para uma “Scroll Jail”, ou seja, um novo elemento com o overflow:scroll. Após isso, o usuário vai achar que está dando o scroll da página, mas na verdade está no Scroll Jail!

Mas não acaba por aí! Para evitar que o usuário dê o scroll até o início dessa “cadeia” e a barra de URL volte a ser exibida, podemos inserir um padding alto no começo da cadeia e, se o usuário tentar rolar para o topo, ele será “puxado” de volta para a base do conteúdo do Scroll Jail.

Esse método de phishing foi encontrado no artigo de título “The inception bar: a new phishing method”, do Jim Fisher (https://jameshfisher.com/2019/04/27/the-inception-bar-a-new-phishing-method/), e a partir da tentativa de reproduzi-lo obtivemos êxito em todos os navegadores presentes nessa pesquisa.

Vejamos na prática como isso acontece:

Vídeo 2 — Exemplo do funcionamento do Scroll Jail no Chrome

Como vimos no vídeo, os ataques de phishing, como por exemplo um formulário solicitando informações sensíveis de sua vítima, podem ganhar maior credibilidade por meio deste ataque, pois ele oculta a URL do site malicioso e mostra a URL verdadeira por meio de uma imagem.

Conclusão

Através das análises realizadas, podemos observar que os navegadores de dispositivos móveis encontram-se vulneráveis a ataques/investidas e merecem mais atenção e mais pesquisas direcionadas, para avaliar sua maturidade e pontos exploráveis. No tempo hábil dessa pesquisa pudemos fazer a análise das quatro vertentes mencionadas acima.

Na Tabela 2, temos os resultados obtidos após a finalização dos testes realizados:

Tabela 2 — Resultado dos testes realizados na pesquisa. O X corresponde aos testes não positivos, e o ✓ aos testes positivos.

O principal obstáculo no decorrer da pesquisa foi encontrar material a respeito dos navegadores móveis, visto que a grande maioria do material sobre browsers está relacionado às versões para desktop.

Para pesquisas futuras, gostaríamos de buscar outras formas de bypass do SOP, como por exemplo analisar como o SOP se comporta diante de diferentes schemas de URL, e também outras formas de bypass do CSP, analisar a forma como os browsers se comportam em relação a aplicações específicas, bem como novos cenários de exploração para a busca de novos problemas de segurança existente em navegadores de dispositivos móveis.

Por fim, é válida a lembrança de que sempre seja feita a verificação dos links antes de carregá-los, verificando se a URL não possui erros de ortografia, evitar clicar diretamente em um link enviado por e-mail, verificar fonte do e-mail, ativar proteções de DLP, entre outros métodos para não se tornar vítima de campanhas de phishing. Além disso, é fortemente recomendado ficar atento às atualizações dos browsers e mantê-los sempre atualizados.

Espero que tenham feito bom proveito da leitura e até a próxima!