MASTG-TEST-0028: Testando Deep Links
Visão Geral¶
Qualquer deep link)) existente (incluindo App Links) pode potencialmente aumentar a superfície de ataque do aplicativo. Isso inclui vários riscos, como sequestro de links, exposição de funcionalidades sensíveis, etc.
- Antes do Android 12 (API level 31), se o aplicativo tiver quaisquer links não verificáveis, isso pode fazer com que o sistema não verifique todos os Android App Links para esse aplicativo.
- A partir do Android 12 (API level 31), os aplicativos se beneficiam de uma superfície de ataque reduzida. Um intent web genérico é resolvido para o aplicativo de navegador padrão do usuário, a menos que o aplicativo de destino seja aprovado para o domínio específico contido nesse intent web.
Todos os deep links devem ser enumerados e verificados quanto à associação correta com o website. As ações que eles executam devem ser bem testadas, especialmente todos os dados de entrada, que devem ser considerados não confiáveis e, portanto, sempre validados.
Nenhum dado de entrada dessas fontes pode ser confiável; ele deve ser validado e/ou sanitizado. A validação garante o processamento apenas dos dados que o aplicativo espera. Se a validação não for aplicada, qualquer entrada pode ser enviada ao aplicativo, o que pode permitir que um atacante ou aplicativo malicioso explore a funcionalidade do aplicativo.
Análise Estática¶
Verificar a Versão do SO Android¶
A versão do Android na qual o aplicativo é executado também influencia o risco do uso de deep links. Inspecione o Android Manifest para verificar se minSdkVersion é 31 ou superior.
- Antes do Android 12 (API level 31), se o aplicativo tiver quaisquer deep links não verificáveis, isso pode fazer com que o sistema não verifique todos os Android App Links para esse aplicativo.
- A partir do Android 12 (API level 31), os aplicativos se beneficiam de uma superfície de ataque reduzida. Um intent web genérico é resolvido para o aplicativo de navegador padrão do usuário, a menos que o aplicativo de destino seja aprovado para o domínio específico contido nesse intent web.
Verificar o Uso de Deep Links¶
Inspecionando o Android Manifest:
Você pode determinar facilmente se deep links (com ou sem esquemas de URL personalizados) são definidos por Explorando o Pacote do Aplicativo e inspecionando o arquivo Android Manifest em busca de elementos <intent-filter>.
- Esquemas de URL Personalizados: O exemplo a seguir especifica um deep link com um esquema de URL personalizado chamado
myapp://.
<activity android:name=".MyUriActivity">
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="myapp" android:host="path" />
</intent-filter>
</activity>
- Deep Links: O exemplo a seguir especifica um deep link usando os esquemas
http://ehttps://, junto com o host e o caminho que o ativará (neste caso, a URL completa seriahttps://www.myapp.com/my/app/path):
<intent-filter>
...
<data android:scheme="http" android:host="www.myapp.com" android:path="/my/app/path" />
<data android:scheme="https" android:host="www.myapp.com" android:path="/my/app/path" />
</intent-filter>
- App Links: Se o
<intent-filter>incluir o atributoandroid:autoVerify="true", isso fará com que o sistema Android acesse oandroid:hostdeclarado na tentativa de acessar o arquivo Digital Asset Links para verificar os App Links. Um deep link só pode ser considerado um App Link se a verificação for bem-sucedida.
<intent-filter android:autoVerify="true">
Ao listar deep links, lembre-se de que os elementos <data> dentro do mesmo <intent-filter> são na verdade mesclados para considerar todas as variações de seus atributos combinados.
<intent-filter>
...
<data android:scheme="https" android:host="www.example.com" />
<data android:scheme="app" android:host="open.my.app" />
</intent-filter>
Pode parecer que isso suporta apenas https://www.example.com e app://open.my.app. No entanto, na verdade suporta:
https://www.example.comapp://open.my.appapp://www.example.comhttps://open.my.app
Usando Dumpsys:
Use adb para executar o seguinte comando que mostrará todos os esquemas:
adb shell dumpsys package com.example.package
Usando o Testador de "Verificação de App Link" do Android:
Use o script Android "App Link Verification" Tester para listar todos os deep links (list-all) ou apenas app links (list-applinks):
python3 deeplink_analyser.py -op list-all -apk ~/Downloads/example.apk
.MainActivity
app://open.my.app
app://www.example.com
https://open.my.app
https://www.example.com
Verificar a Associação Correta com o Website¶
Mesmo que os deep links contenham o atributo android:autoVerify="true", eles devem ser realmente verificados para serem considerados App Links. Você deve testar quaisquer possíveis configurações incorretas que possam impedir a verificação completa.
Verificação Automática¶
Use o script Android "App Link Verification" Tester para obter o status de verificação de todos os app links (verify-applinks). Veja um exemplo aqui.
Somente no Android 12 (API level 31) ou superior:
Você pode usar adb para testar a lógica de verificação, independentemente de o aplicativo ter como destino o Android 12 (API level 31) ou não. Este recurso permite que você:
- invocar manualmente o processo de verificação.
- redefinir o estado dos Android App Links do aplicativo de destino no seu dispositivo.
- invocar o processo de verificação de domínio.
Você também pode revisar os resultados da verificação. Por exemplo:
adb shell pm get-app-links com.example.package
com.example.package:
ID: 01234567-89ab-cdef-0123-456789abcdef
Signatures: [***]
Domain verification state:
example.com: verified
sub.example.com: legacy_failure
example.net: verified
example.org: 1026
A mesma informação pode ser encontrada executando
adb shell dumpsys package com.example.package(somente no Android 12 (API level 31) ou superior).
Verificação Manual¶
Esta seção detalha alguns, de possivelmente muitos, motivos pelos quais o processo de verificação falhou ou não foi realmente acionado. Veja mais informações na Documentação para Desenvolvedores Android e no white paper "Measuring the Insecurity of Mobile Deep Links of Android".
Verificar o arquivo Digital Asset Links:
- Verificar se o arquivo Digital Asset Links está faltando:
- tente encontrá-lo no caminho
/.well-known/do domínio. Exemplo:https://www.example.com/.well-known/assetlinks.json - ou tente
https://digitalassetlinks.googleapis.com/v1/statements:list?source.web.site=www.example.com
- tente encontrá-lo no caminho
- Verificar se o arquivo Digital Asset Links válido é servido via HTTP.
- Verificar se os arquivos Digital Asset Links inválidos são servidos via HTTPS. Por exemplo:
- o arquivo contém JSON inválido.
- o arquivo não inclui o pacote do aplicativo de destino.
Verificar Redirecionamentos:
Para melhorar a segurança do aplicativo, o sistema não verifica nenhum Android App Link para um aplicativo se o servidor definir um redirecionamento, como http://example.com para https://example.com ou example.com para www.example.com.
Verificar Subdomínios:
Se um filtro de intent listar vários hosts com subdomínios diferentes, deve haver um arquivo Digital Asset Links válido em cada domínio. Por exemplo, o seguinte filtro de intent inclui www.example.com e mobile.example.com como hosts de URL de intent aceitos.
<application>
<activity android:name=”MainActivity”>
<intent-filter android:autoVerify="true">
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="https" />
<data android:scheme="https" />
<data android:host="www.example.com" />
<data android:host="mobile.example.com" />
</intent-filter>
</activity>
</application>
Para que os deep links sejam registrados corretamente, um arquivo Digital Asset Links válido deve ser publicado em https://www.example.com/.well-known/assetlinks.json e https://mobile.example.com/.well-known/assetlinks.json.
Verificar Caracteres Curinga:
Se o nome do host incluir um caractere curinga (como *.example.com), você deve ser capaz de encontrar um arquivo Digital Asset Links válido no nome do host raiz: https://example.com/.well-known/assetlinks.json.
Verificar o Método Manipulador¶
Mesmo que o deep link seja verificado corretamente, a lógica do método manipulador deve ser cuidadosamente analisada. Preste atenção especial aos deep links sendo usados para transmitir dados (que são controlados externamente pelo usuário ou por qualquer outro aplicativo).
Primeiro, obtenha o nome da Activity a partir do elemento <activity> do Android Manifest que define o <intent-filter> de destino e procure pelo uso de getIntent e getData. Essa abordagem geral de localizar esses métodos pode ser usada na maioria dos aplicativos ao realizar engenharia reversa e é fundamental ao tentar entender como o aplicativo usa deep links e manipula quaisquer dados de entrada fornecidos externamente e se eles podem estar sujeitos a qualquer tipo de abuso.
O exemplo a seguir é um trecho de um aplicativo Kotlin de exemplo descompilado com jadx. A partir da análise estática)) sabemos que ele suporta o deep link deeplinkdemo://load.html/ como parte de com.mstg.deeplinkdemo.WebViewActivity.
// trecho editado para simplicidade
public final class WebViewActivity extends AppCompatActivity {
private ActivityWebViewBinding binding;
public void onCreate(Bundle savedInstanceState) {
Uri data = getIntent().getData();
String html = data == null ? null : data.getQueryParameter("html");
Uri data2 = getIntent().getData();
String deeplink_url = data2 == null ? null : data2.getQueryParameter("url");
View findViewById = findViewById(R.id.webView);
if (findViewById != null) {
WebView wv = (WebView) findViewById;
wv.getSettings().setJavaScriptEnabled(true);
if (deeplink_url != null) {
wv.loadUrl(deeplink_url);
...
Você pode simplesmente seguir a variável String deeplink_url e ver o resultado da chamada wv.loadUrl. Isso significa que o atacante tem controle total da URL sendo carregada no WebView (como mostrado acima tem Teste de Execução JavaScript em WebViews).
O mesmo WebView também pode estar renderizando um parâmetro controlado pelo atacante. Nesse caso, o seguinte payload de deep link acionaria Cross-Site Scripting (XSS) Refletido)) dentro do contexto do WebView:
deeplinkdemo://load.html?attacker_controlled=<svg onload=alert(1)>
Mas há muitas outras possibilidades. Certifique-se de verificar as seguintes seções para saber o que esperar e como testar diferentes cenários:
- "Falhas de Cross-Site Scripting")).
- "Falhas de Injeção")).
- Testando Persistência de Objetos.
- Teste de Carregamento de URL em WebViews
- Teste de Execução JavaScript em WebViews
- Testando Manipuladores de Protocolo do WebView
Além disso, recomendamos pesquisar e ler relatórios públicos (termo de pesquisa: "deep link*"|"deeplink*" site:https://hackerone.com/reports/). Por exemplo:
- "[HackerOne#1372667] Able to steal bearer token from deep link"
- "[HackerOne#401793] Insecure deeplink leads to sensitive information disclosure"
- "[HackerOne#583987] Android app deeplink leads to CSRF in follow action"
- "[HackerOne#637194] Bypass of biometrics security functionality is possible in Android application"
- "[HackerOne#341908] XSS via Direct Message deeplinks"
Análise Dinâmica¶
Aqui você usará a lista de deep links da análise estática para iterar e determinar cada método manipulador e os dados processados, se houver. Você primeiro iniciará um hook do Frida e, em seguida, começará a invocar os deep links.
O exemplo a seguir assume um aplicativo de destino que aceita este deep link: deeplinkdemo://load.html. No entanto, ainda não sabemos o método manipulador correspondente, nem os parâmetros que ele potencialmente aceita.
[Passo 1] Hooking com Frida:
Você pode usar o script "Android Deep Link Observer" do Frida CodeShare para monitorar todos os deep links invocados que disparam uma chamada para Intent.getData. Você também pode usar o script como base para incluir suas próprias modificações, dependendo do caso de uso em questão. Neste caso, incluímos o stack trace no script, pois estamos interessados no método que chama Intent.getData.
[Passo 2] Invocando Deep Links:
Agora você pode invocar qualquer um dos deep links usando adb e o Activity Manager (am), que enviará intents dentro do dispositivo Android. Por exemplo:
adb shell am start -W -a android.intent.action.VIEW -d "deeplinkdemo://load.html/?message=ok#part1"
Starting: Intent { act=android.intent.action.VIEW dat=deeplinkdemo://load.html/?message=ok }
Status: ok
LaunchState: WARM
Activity: com.mstg.deeplinkdemo/.WebViewActivity
TotalTime: 210
WaitTime: 217
Complete
Isso pode acionar o diálogo de desambiguação ao usar o esquema "http/https" ou se outros aplicativos instalados suportarem o mesmo esquema de URL personalizado. Você pode incluir o nome do pacote para torná-lo um intent explícito.
Esta invocação registrará o seguinte:
[*] Intent.getData() foi chamado
[*] Activity: com.mstg.deeplinkdemo.WebViewActivity
[*] Action: android.intent.action.VIEW
[*] Data
- Scheme: deeplinkdemo://
- Host: /load.html
- Params: message=ok
- Fragment: part1
[*] Stacktrace:
android.content.Intent.getData(Intent.java)
com.mstg.deeplinkdemo.WebViewActivity.onCreate(WebViewActivity.kt)
android.app.Activity.performCreate(Activity.java)
...
com.android.internal.os.ZygoteInit.main(ZygoteInit.java)
Neste caso, criamos o deep link incluindo parâmetros arbitrários (?message=ok) e fragmento (#part1). Ainda não sabemos se eles estão sendo usados. As informações acima revelam informações úteis que você pode usar agora para fazer engenharia reversa do aplicativo. Consulte a seção "Verificar o Método Manipulador")) para saber sobre coisas que você deve considerar.
- Arquivo:
WebViewActivity.kt - Classe:
com.mstg.deeplinkdemo.WebViewActivity - Método:
onCreate
Às vezes, você pode até aproveitar outros aplicativos que você sabe que interagem com seu aplicativo de destino. Você pode fazer engenharia reversa do aplicativo (por exemplo, para extrair todas as strings e filtrar aquelas que incluem os deep links de destino,
deeplinkdemo:///load.htmlno caso anterior) ou usá-los como gatilhos, enquanto faz hooking no aplicativo como discutido anteriormente.