Categoria do OWASP: MASVS-PLATFORM - Interação com plataformas
Visão geral
Uma ponte nativa, às vezes conhecida como ponte JavaScript, é um mecanismo que
facilita a comunicação entre um WebView e o código nativo do Android, usando o método addJavascriptInterface. Isso permite a comunicação bidirecional entre o código JavaScript em execução no WebView e o código Java do aplicativo Android. O método addJavascriptInterface expõe um objeto Java a todos os frames de um WebView, e qualquer frame pode acessar o nome do objeto e chamar métodos nele. No entanto, não há um mecanismo para o aplicativo verificar a origem do frame de chamada no WebView, o que levanta preocupações de segurança, já que a confiabilidade do conteúdo permanece indeterminada.
Uma ponte nativa também pode ser implementada com canais de mensagens HTML usando
o WebViewCompat.postWebMessage ou
WebMessagePort.postMessage do Android para se comunicar com o JavaScript
Window.postMessage. WebViewCompat.postWebMessage e WebMessagePort.postMessage podem aceitar mensagens JavaScript enviadas por Window.postMessage, que serão executadas no WebView.
Há vários riscos associados a pontes nativas:
- Pontes baseadas em JavascriptInterface:
- O método
addJavascriptInterfaceinjeta um objeto Java fornecido em todos os frames do WebView, incluindo iframes, o que significa que ele é suscetível a ataques de terceiros maliciosos que injetam frames em um site legítimo. Os aplicativos destinados ao nível 16 da API ou anterior correm um risco maior de ataque, porque esse método pode ser usado para permitir que o JavaScript controle o aplicativo host. - Refletir conteúdo não confiável fornecido pelo usuário em WebViews ativados por pontes nativas permite ataques de scripting em vários sites (XSS).
- O método
- Pontes baseadas em MessageChannel:
- A falta de verificações de origem nos endpoints do canal de mensagens significa que as mensagens serão aceitas de qualquer remetente, incluindo aquelas que contêm código malicioso.
- É possível expor o Java acidentalmente a JavaScript arbitrário.
Impacto
Os métodos addJavascriptInterface, postWebMessage e postMessage podem ser usados por agentes maliciosos para acessar, manipular ou injetar código controlado em um WebView. Isso pode levar os usuários a serem redirecionados para sites maliciosos, carregar conteúdo malicioso ou executar código malicioso nos dispositivos que podem extrair dados sensíveis ou alcançar o escalonamento de privilégios.
Risco: riscos de addJavascriptInterface
O WebView implementa funcionalidades básicas de um navegador, como renderização de páginas, navegação e execução de JavaScript. O WebView pode ser usado em um aplicativo para mostrar conteúdo da Web como parte de um layout de atividade. A implementação de uma ponte nativa em um WebView usando o método addJavascriptInterface pode criar problemas de segurança, como scripting em vários sites (XSS), ou permitir que invasores carreguem conteúdo não confiável por injeção de interface e manipulem o aplicativo host de maneiras não intencionais, executando código Java com as permissões do aplicativo host.
Mitigações
Desativar JavaScript
Em cenários em que o WebView não exige JavaScript, não chame
setJavaScriptEnabled em WebSettings (por exemplo, ao
mostrar conteúdo HTML estático). Por padrão, a execução de JavaScript está desativada no WebView.
Remover a interface JavaScript ao carregar conteúdo não confiável
Confirme se os objetos da interface JavaScript foram removidos chamando
removeJavascriptInterface antes que o conteúdo não confiável seja carregado pelo
WebView. Por exemplo, isso pode ser feito em uma chamada para
shouldInterceptRequest.
Kotlin
webView.removeJavascriptInterface("myObject")
Java
webView.removeJavascriptInterface("myObject");
Carregar conteúdo da Web somente por HTTPS
Se você precisar carregar conteúdo não confiável, confirme se o WebView carrega conteúdo da Web em uma conexão criptografada (consulte também nossas diretrizes sobre Comunicações
de texto não criptografado). Para evitar que o carregamento de página inicial seja realizado em conexões não criptografadas, defina android:usesCleartextTraffic como false no arquivo AndroidManifest ou impeça o tráfego HTTP em uma configuração de segurança de rede. Consulte a documentação usesCleartextTraffic para mais
informações.
XML
<application
android:usesCleartextTraffic="false">
<!-- Other application elements -->
</application>
Para garantir que os redirecionamentos e a navegação adicional do app não ocorram em tráfego não criptografado, verifique o esquema HTTP em loadUrl ou
shouldInterceptRequest:
Kotlin
fun loadSecureUrl(webView: WebView?, url: String?) {
webView?.let { wv -> // Ensure valid WebView and URL
url?.let {
try {
val uri = URI(url)
if (uri.scheme.equals("https", ignoreCase = true)) { // Enforce HTTPS scheme for security
wv.loadUrl(url)
} else {
// Log an error or handle the case where the URL is not secure
System.err.println("Attempted to load a non-HTTPS URL: $url")
}
} catch (e: Exception) {
// Handle exception for improper URL format
System.err.println("Invalid URL syntax: $url")
}
}
}
}
Java
public void loadSecureUrl(WebView webView, String url) {
if (webView != null && url != null) { // Ensure valid WebView and URL
try {
URI uri = new URI(url);
String scheme = uri.getScheme();
if ("https".equalsIgnoreCase(scheme)) { // Enforce HTTPS scheme for security
webView.loadUrl(url);
} else {
// Log an error or handle the case where the URL is not secure
System.err.println("Attempted to load a non-HTTPS URL: " + url);
}
} catch (URISyntaxException e) {
// Handle exception for improper URL format
System.err.println("Invalid URL syntax: " + url);
}
}
}
Validar conteúdo não confiável
Se algum link externo for carregado em um WebView, valide o esquema e o host (domínios da lista de permissões). Os domínios que não estão na lista de permissões precisam ser abertos pelo navegador padrão.
Não carregar conteúdo não confiável
Se possível, carregue apenas URLs com escopo restrito e conteúdo de propriedade do desenvolvedor do app no WebView.
Não expor dados sensíveis
Se o aplicativo acessar dados sensíveis com um WebView, use o
clearCache método para excluir arquivos armazenados localmente antes de usar a
interface JavaScript. Você também pode usar cabeçalhos do lado do servidor, como no-store, para indicar que um aplicativo não deve armazenar em cache conteúdos específicos.
Não expor funcionalidades sensíveis
Se o aplicativo exigir permissões sensíveis ou coletar dados sensíveis, confirme se ele é chamado do código no aplicativo e se a divulgação em destaque é fornecida aos usuários. Evite usar interfaces JavaScript para operações sensíveis ou dados do usuário.
Nível desejado da API 21 ou superior
Uma maneira segura de usar o método addJavascriptInterface é segmentar o nível desejado da API 21 ou mais recente, garantindo que o método seja chamado apenas quando executado no nível da API 21 ou mais recente. Antes da API 21, o JavaScript podia usar a reflexão para acessar os campos públicos de um objeto injetado.
Risco: riscos de MessageChannel
A falta de controle de origem em postWebMessage() e postMessage() pode permitir que invasores interceptem mensagens ou enviem mensagens para handlers nativos.
Mitigações
Ao configurar postWebMessage() ou postMessage(), permita apenas mensagens de domínios confiáveis, evitando o uso de * como a origem de destino e, em vez disso, especifique explicitamente o domínio de envio esperado.
Recursos
- Práticas recomendadas de postMessage()
- Documentação de addJavascriptInterface
- Documentação de postMessage()
- Documentação de WebMessagePort.postMessage()
- Documentação de WebViewClient.shouldInterceptRequest
- Documentação de recomendações de segurança sobre addJavascriptInterface
- Documentação de clearCache
- Documentação de removeJavascript
- Como ativar o JavaScript em WebViews