hacktricks/mobile-pentesting/ios-pentesting/ios-custom-uri-handlers-deeplinks-custom-schemes.md

14 KiB

Aprenda hacking no AWS do zero ao herói com htARTE (HackTricks AWS Red Team Expert)!

Outras formas de apoiar o HackTricks:

Esquemas de URL personalizados permitem que aplicativos se comuniquem via um protocolo personalizado. Um aplicativo deve declarar suporte para os esquemas e tratar URLs de entrada que utilizem esses esquemas.

Esquemas de URL oferecem um vetor de ataque potencial para seu aplicativo, então certifique-se de validar todos os parâmetros da URL e descartar quaisquer URLs malformadas. Além disso, limite as ações disponíveis àquelas que não arrisquem os dados do usuário.

Por exemplo, a URI: myapp://hostname?data=123876123 irá invocar o aplicativo mydata (aquele que registrou o esquema mydata) para a ação relacionada ao hostname hostname enviando o parâmetro data com valor 123876123

Um exemplo vulnerável é o seguinte bug no aplicativo móvel Skype, descoberto em 2010: O aplicativo Skype registrou o manipulador de protocolo skype://, que permitia que outros aplicativos iniciassem chamadas para outros usuários do Skype e números de telefone. Infelizmente, o Skype não pedia permissão aos usuários antes de fazer as chamadas, então qualquer aplicativo poderia ligar para números arbitrários sem o conhecimento do usuário. Os atacantes exploraram essa vulnerabilidade colocando um <iframe src="skype://xxx?call"></iframe> invisível (onde xxx foi substituído por um número premium), então qualquer usuário do Skype que visitasse inadvertidamente um site malicioso chamaria o número premium.

Você pode encontrar os esquemas registrados por um aplicativo no arquivo Info.plist do aplicativo procurando por CFBundleURLTypes (exemplo de iGoat-Swift):

<key>CFBundleURLTypes</key>
<array>
<dict>
<key>CFBundleURLName</key>
<string>com.iGoat.myCompany</string>
<key>CFBundleURLSchemes</key>
<array>
<string>iGoat</string>
</array>
</dict>
</array>

No entanto, observe que aplicações maliciosas podem re-registrar URIs já registradas por aplicações. Então, se você está enviando informações sensíveis via URIs (myapp://hostname?password=123456), uma aplicação maliciosa pode interceptar a URI com a informação sensível.

Além disso, a entrada dessas URIs deve ser verificada e higienizada, pois pode vir de origens maliciosas tentando explorar SQLInjections, XSS, CSRF, Path Traversals ou outras possíveis vulnerabilidades.

Registro de Esquemas de Consulta de Aplicativos

Aplicativos podem chamar canOpenURL: para verificar se o aplicativo alvo está disponível. No entanto, como este método estava sendo usado por aplicativos maliciosos como uma forma de enumerar aplicativos instalados, a partir do iOS 9.0 os esquemas de URL passados para ele também devem ser declarados adicionando a chave LSApplicationQueriesSchemes ao arquivo Info.plist do aplicativo e um array de até 50 esquemas de URL.

<key>LSApplicationQueriesSchemes</key>
<array>
<string>url_scheme1</string>
<string>url_scheme2</string>
</array>

canOpenURL sempre retornará NO para esquemas não declarados, independentemente de haver ou não um aplicativo apropriado instalado. No entanto, essa restrição se aplica apenas ao canOpenURL.

Testando o Manuseio e Validação de URL

Para determinar como um caminho de URL é construído e validado, se você tem o código-fonte original, você pode procurar pelos seguintes métodos:

  • método application:didFinishLaunchingWithOptions: ou application:willFinishLaunchingWithOptions:: verifique como a decisão é tomada e como as informações sobre a URL são recuperadas.
  • application:openURL:options:: verifique como o recurso está sendo aberto, ou seja, como os dados estão sendo analisados, verifique as opções, especialmente se o acesso pelo aplicativo chamador (sourceApplication) deve ser permitido ou negado. O aplicativo também pode precisar de permissão do usuário ao usar o esquema de URL personalizado.

No Telegram, você encontrará quatro métodos diferentes sendo usados:

func application(_ application: UIApplication, open url: URL, sourceApplication: String?) -> Bool {
self.openUrl(url: url)
return true
}

func application(_ application: UIApplication, open url: URL, sourceApplication: String?,
annotation: Any) -> Bool {
self.openUrl(url: url)
return true
}

func application(_ app: UIApplication, open url: URL,
options: [UIApplicationOpenURLOptionsKey : Any] = [:]) -> Bool {
self.openUrl(url: url)
return true
}

func application(_ application: UIApplication, handleOpen url: URL) -> Bool {
self.openUrl(url: url)
return true
}

Testando Requisições de URL para Outros Apps

O método openURL:options:completionHandler: e o método deprecated openURL: de UIApplication são responsáveis por abrir URLs (ou seja, para enviar requisições / fazer consultas a outros apps) que podem ser locais ao app atual ou podem ser fornecidos por um app diferente. Se você tem o código-fonte original, pode procurar diretamente pelo uso desses métodos.

Adicionalmente, se você tem interesse em saber se o app está consultando serviços ou apps específicos, e se o app é bem conhecido, você também pode procurar por esquemas de URL comuns online e incluí-los em seus greps (lista de esquemas de apps iOS)**.

egrep -nr "open.*options.*completionHandler" ./Telegram-iOS/
egrep -nr "openURL\(" ./Telegram-iOS/
egrep -nr "mt-encrypted-file://" ./Telegram-iOS/
egrep -nr "://" ./Telegram-iOS/

Testando Métodos Obsoletos

Procure por métodos obsoletos como:

Por exemplo, aqui encontramos esses três:

$ rabin2 -zzq Telegram\ X.app/Telegram\ X | grep -i "openurl"

0x1000d9e90 31 30 UIApplicationOpenURLOptionsKey
0x1000dee3f 50 49 application:openURL:sourceApplication:annotation:
0x1000dee71 29 28 application:openURL:options:
0x1000dee8e 27 26 application:handleOpenURL:
0x1000df2c9 9 8 openURL:
0x1000df766 12 11 canOpenURL:
0x1000df772 35 34 openURL:options:completionHandler:
...

Chamando URLs arbitrárias

  • Safari: Para testar rapidamente um esquema de URL, você pode abrir as URLs no Safari e observar como o aplicativo se comporta. Por exemplo, se você escrever tel://123456789 o Safari tentará iniciar a chamada para o número.
  • Aplicativo de Notas: Pressione e segure os links que você escreveu para testar esquemas de URL personalizados. Lembre-se de sair do modo de edição para poder abri-los. Observe que você pode clicar ou pressionar e segurar links incluindo esquemas de URL personalizados apenas se o aplicativo estiver instalado, caso contrário, eles não serão destacados como links clicáveis.
  • IDB:
  • Inicie o IDB, conecte-se ao seu dispositivo e selecione o aplicativo alvo. Você pode encontrar detalhes na documentação do IDB.
  • Vá para a seção URL Handlers. Em URL schemes, clique em Refresh, e à esquerda você encontrará uma lista de todos os esquemas personalizados definidos no aplicativo em teste. Você pode carregar esses esquemas clicando em Open, no lado direito. Simplesmente abrindo um esquema de URI em branco (por exemplo, abrindo myURLscheme://), você pode descobrir funcionalidades ocultas (por exemplo, uma janela de depuração) e contornar a autenticação local.
  • Frida:

Se você simplesmente quer abrir o esquema de URL, pode fazer isso usando Frida:

$ frida -U iGoat-Swift

[iPhone::iGoat-Swift]-> function openURL(url) {
var UIApplication = ObjC.classes.UIApplication.sharedApplication();
var toOpen = ObjC.classes.NSURL.URLWithString_(url);
return UIApplication.openURL_(toOpen);
}
[iPhone::iGoat-Swift]-> openURL("tel://234234234")
true

Neste exemplo do Frida CodeShare o autor usa a API não pública LSApplicationWorkspace.openSensitiveURL:withOptions: para abrir as URLs (do aplicativo SpringBoard):

function openURL(url) {
var w = ObjC.classes.LSApplicationWorkspace.defaultWorkspace();
var toOpen = ObjC.classes.NSURL.URLWithString_(url);
return w.openSensitiveURL_withOptions_(toOpen, null);
}

Observe que o uso de APIs não públicas não é permitido na App Store, é por isso que nem testamos essas, mas estamos autorizados a usá-las para nossa análise dinâmica.

Fuzzing de Esquemas de URL

Se o aplicativo analisa partes da URL, você também pode realizar fuzzing de entrada para detectar bugs de corrupção de memória.

O que aprendemos acima pode agora ser usado para construir seu próprio fuzzer no idioma de sua escolha, por exemplo, em Python e chamar o openURL usando RPC do Frida. Esse fuzzer deve fazer o seguinte:

  • Gerar cargas úteis.
  • Para cada uma delas, chamar openURL.
  • Verificar se o aplicativo gera um relatório de falhas (.ips) em /private/var/mobile/Library/Logs/CrashReporter.

O projeto FuzzDB oferece dicionários de fuzzing que você pode usar como cargas úteis.

Fuzzing Usando Frida

Fazer isso com Frida é bastante fácil, você pode se referir a este post do blog para ver um exemplo que faz fuzzing no aplicativo iGoat-Swift (funcionando no iOS 11.1.2).

Antes de executar o fuzzer, precisamos dos esquemas de URL como entradas. A partir da análise estática, sabemos que o aplicativo iGoat-Swift suporta o seguinte esquema de URL e parâmetros: iGoat://?contactNumber={0}&message={0}.

$ frida -U SpringBoard -l ios-url-scheme-fuzzing.js
[iPhone::SpringBoard]-> fuzz("iGoat", "iGoat://?contactNumber={0}&message={0}")
Watching for crashes from iGoat...
No logs were moved.
Opened URL: iGoat://?contactNumber=0&message=0

Referências

{% embed url="https://mobile-security.gitbook.io/mobile-security-testing-guide/ios-testing-guide/0x06h-testing-platform-interaction#testing-object-persistence-mstg-platform-8" %}

Aprenda hacking no AWS do zero ao herói com htARTE (HackTricks AWS Red Team Expert)!

Outras formas de apoiar o HackTricks: