hacktricks/mobile-pentesting/ios-pentesting/ios-custom-uri-handlers-deeplinks-custom-schemes.md
2023-06-03 13:10:46 +00:00

198 lines
16 KiB
Markdown

<details>
<summary><a href="https://cloud.hacktricks.xyz/pentesting-cloud/pentesting-cloud-methodology"><strong>☁️ HackTricks Cloud ☁️</strong></a> -<a href="https://twitter.com/hacktricks_live"><strong>🐦 Twitter 🐦</strong></a> - <a href="https://www.twitch.tv/hacktricks_live/schedule"><strong>🎙️ Twitch 🎙️</strong></a> - <a href="https://www.youtube.com/@hacktricks_LIVE"><strong>🎥 Youtube 🎥</strong></a></summary>
- Travaillez-vous dans une entreprise de **cybersécurité** ? Voulez-vous voir votre **entreprise annoncée dans HackTricks** ? ou voulez-vous avoir accès à la **dernière version de PEASS ou télécharger HackTricks en PDF** ? Consultez les [**PLANS D'ABONNEMENT**](https://github.com/sponsors/carlospolop) !
- Découvrez [**The PEASS Family**](https://opensea.io/collection/the-peass-family), notre collection exclusive de [**NFTs**](https://opensea.io/collection/the-peass-family)
- Obtenez le [**swag officiel PEASS & HackTricks**](https://peass.creator-spring.com)
- **Rejoignez le** [**💬**](https://emojipedia.org/speech-balloon/) [**groupe Discord**](https://discord.gg/hRep4RUj7f) ou le [**groupe telegram**](https://t.me/peass) ou **suivez** moi sur **Twitter** [**🐦**](https://github.com/carlospolop/hacktricks/tree/7af18b62b3bdc423e11444677a6a73d4043511e9/\[https:/emojipedia.org/bird/README.md)[**@carlospolopm**](https://twitter.com/hacktricks_live)**.**
- **Partagez vos astuces de piratage en soumettant des PR au [repo hacktricks](https://github.com/carlospolop/hacktricks) et au [repo hacktricks-cloud](https://github.com/carlospolop/hacktricks-cloud)**.
</details>
Les schémas d'URL personnalisés [permettent aux applications de communiquer via un protocole personnalisé](https://developer.apple.com/library/content/documentation/iPhone/Conceptual/iPhoneOSProgrammingGuide/Inter-AppCommunication/Inter-AppCommunication.html#//apple\_ref/doc/uid/TP40007072-CH6-SW1). Une application doit déclarer la prise en charge des schémas et gérer les URL entrantes qui utilisent ces schémas.
> Les schémas d'URL offrent un vecteur d'attaque potentiel dans votre application, alors assurez-vous de **valider tous les paramètres d'URL** et de **rejeter tout URL malformé**. De plus, limitez les **actions** disponibles à celles qui ne risquent pas les données de l'utilisateur.
Par exemple, l'URI : `myapp://hostname?data=123876123` **déclenchera** l'**application** mydata (celle qui a **enregistré** le schéma `mydata`) pour l'**action** liée à l'**hostname** `hostname` en envoyant le **paramètre** `data` avec la valeur `123876123`.
Un exemple vulnérable est le [bug dans l'application mobile Skype](http://www.dhanjani.com/blog/2010/11/insecure-handling-of-url-schemes-in-apples-ios.html), découvert en 2010 : l'application Skype a enregistré le gestionnaire de protocole `skype://`, ce qui a **permis à d'autres applications de déclencher des appels vers d'autres utilisateurs Skype et des numéros de téléphone**. Malheureusement, Skype n'a pas demandé la permission des utilisateurs avant de passer les appels, de sorte que n'importe quelle application pouvait appeler des numéros arbitraires sans la connaissance de l'utilisateur. Les attaquants ont exploité cette vulnérabilité en mettant en place un `<iframe src="skype://xxx?call"></iframe>` invisible (où `xxx` était remplacé par un numéro premium), de sorte que tout utilisateur Skype qui a visité involontairement un site Web malveillant a appelé le numéro premium.
Vous pouvez trouver les **schémas enregistrés par une application** dans le fichier **`Info.plist`** de l'application en recherchant **`CFBundleURLTypes`** (exemple de [iGoat-Swift](https://github.com/OWASP/iGoat-Swift)) :
```markup
<key>CFBundleURLTypes</key>
<array>
<dict>
<key>CFBundleURLName</key>
<string>com.iGoat.myCompany</string>
<key>CFBundleURLSchemes</key>
<array>
<string>iGoat</string>
</array>
</dict>
</array>
```
Cependant, notez que les applications malveillantes peuvent réenregistrer des URI déjà enregistrées par d'autres applications. Ainsi, si vous envoyez des informations sensibles via des URI (myapp://hostname?password=123456), une application malveillante peut intercepter l'URI avec les informations sensibles.
De plus, l'entrée de ces URI doit être vérifiée et nettoyée, car elle peut provenir d'origines malveillantes cherchant à exploiter des failles telles que les injections SQL, XSS, CSRF, les traversées de chemin ou d'autres vulnérabilités possibles.
## Enregistrement des schémas de requête d'application
Les applications peuvent appeler [`canOpenURL:`](https://developer.apple.com/documentation/uikit/uiapplication/1622952-canopenurl?language=objc) pour vérifier que l'application cible est disponible. Cependant, comme cette méthode était utilisée par des applications malveillantes pour énumérer les applications installées, [à partir d'iOS 9.0, les schémas d'URL passés doivent également être déclarés](https://developer.apple.com/documentation/uikit/uiapplication/1622952-canopenurl?language=objc#discussion) en ajoutant la clé `LSApplicationQueriesSchemes` au fichier `Info.plist` de l'application et un tableau d'**au plus 50 schémas d'URL**.
```markup
<key>LSApplicationQueriesSchemes</key>
<array>
<string>url_scheme1</string>
<string>url_scheme2</string>
</array>
```
`canOpenURL` renverra toujours `NO` pour les schémas non déclarés, que l'application appropriée soit installée ou non. Cependant, cette restriction ne s'applique qu'à `canOpenURL`.
## Test de la gestion et de la validation des URL
Afin de déterminer comment un chemin d'URL est construit et validé, si vous avez le code source original, vous pouvez **rechercher les méthodes suivantes** :
* Méthode `application:didFinishLaunchingWithOptions:` ou `application:will-FinishLaunchingWithOptions:` : vérifiez comment la décision est prise et comment les informations sur l'URL sont récupérées.
* [`application:openURL:options:`](https://developer.apple.com/documentation/uikit/uiapplicationdelegate/1623112-application?language=objc) : vérifiez comment la ressource est ouverte, c'est-à-dire comment les données sont analysées, vérifiez les [options](https://developer.apple.com/documentation/uikit/uiapplication/openurloptionskey), en particulier si l'accès par l'application appelante ([`sourceApplication`](https://developer.apple.com/documentation/uikit/uiapplication/openurloptionskey/1623128-sourceapplication)) doit être autorisé ou refusé. L'application peut également avoir besoin de l'autorisation de l'utilisateur lors de l'utilisation du schéma d'URL personnalisé.
Dans Telegram, vous trouverez [quatre méthodes différentes utilisées](https://github.com/peter-iakovlev/Telegram-iOS/blob/87e0a33ac438c1d702f2a0b75bf21f26866e346f/Telegram-iOS/AppDelegate.swift#L1250) :
```swift
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
}
```
## Tester les requêtes d'URL vers d'autres applications
La méthode [`openURL:options:completionHandler:`](https://developer.apple.com/documentation/uikit/uiapplication/1648685-openurl?language=objc) et la méthode [`openURL:`](https://developer.apple.com/documentation/uikit/uiapplication/1622961-openurl?language=objc) de `UIApplication` (dépréciée) sont responsables de l'**ouverture d'URLs** (c'est-à-dire pour envoyer des requêtes / faire des requêtes à d'autres applications) qui peuvent être locales à l'application actuelle ou qui doivent être fournies par une autre application. Si vous avez le code source original, vous pouvez rechercher directement les utilisations de ces méthodes.
De plus, si vous êtes intéressé à savoir si l'application interroge des services ou des applications spécifiques, et si l'application est bien connue, vous pouvez également rechercher des schémas d'URL courants en ligne et les inclure dans vos **greps (liste des schémas d'applications iOS)**.
```bash
egrep -nr "open.*options.*completionHandler" ./Telegram-iOS/
egrep -nr "openURL\(" ./Telegram-iOS/
egrep -nr "mt-encrypted-file://" ./Telegram-iOS/
egrep -nr "://" ./Telegram-iOS/
```
## Test de méthodes obsolètes
Recherchez des méthodes obsolètes telles que :
* [`application:handleOpenURL:`](https://developer.apple.com/documentation/uikit/uiapplicationdelegate/1622964-application?language=objc)
* [`openURL:`](https://developer.apple.com/documentation/uikit/uiapplication/1622961-openurl?language=objc)
* [`application:openURL:sourceApplication:annotation:`](https://developer.apple.com/documentation/uikit/uiapplicationdelegate/1623073-application)
Par exemple, nous trouvons ces trois méthodes :
```bash
$ 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:
...
```
## Appel d'URL arbitraires
* **Safari**: Pour tester rapidement un schéma d'URL, vous pouvez ouvrir les URL sur Safari et observer le comportement de l'application. Par exemple, si vous écrivez `tel://123456789`, Safari essaiera de commencer l'appel du numéro.
* **Notes App**: Appuyez longuement sur les liens que vous avez écrits pour tester les schémas d'URL personnalisés. N'oubliez pas de quitter le mode d'édition pour pouvoir les ouvrir. Notez que vous pouvez cliquer ou appuyer longuement sur des liens incluant des schémas d'URL personnalisés uniquement si l'application est installée, sinon ils ne seront pas mis en évidence en tant que _liens cliquables_.
* [**IDB**](https://github.com/facebook/idb):
* Démarrez IDB, connectez-vous à votre appareil et sélectionnez l'application cible. Vous pouvez trouver des détails dans la [documentation IDB](https://www.idbtool.com/documentation/setup.html).
* Allez à la section **URL Handlers**. Dans les **URL schemes**, cliquez sur **Refresh**, et sur la gauche, vous trouverez une liste de tous les schémas personnalisés définis dans l'application testée. Vous pouvez charger ces schémas en cliquant sur **Open**, sur le côté droit. En ouvrant simplement un schéma d'URI vide (par exemple, en ouvrant `myURLscheme://`), vous pouvez découvrir des fonctionnalités cachées (par exemple, une fenêtre de débogage) et contourner l'authentification locale.
* **Frida**:
Si vous voulez simplement ouvrir le schéma d'URL, vous pouvez le faire en utilisant Frida :
```javascript
$ 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
```
Dans cet exemple de [Frida CodeShare](https://codeshare.frida.re/@dki/ios-url-scheme-fuzzing/), l'auteur utilise l'API non publique `LSApplicationWorkspace.openSensitiveURL:withOptions:` pour ouvrir les URL (à partir de l'application SpringBoard) :
```javascript
function openURL(url) {
var w = ObjC.classes.LSApplicationWorkspace.defaultWorkspace();
var toOpen = ObjC.classes.NSURL.URLWithString_(url);
return w.openSensitiveURL_withOptions_(toOpen, null);
}
```
> Notez que l'utilisation d'API non publiques n'est pas autorisée sur l'App Store, c'est pourquoi nous ne les testons même pas, mais nous sommes autorisés à les utiliser pour notre analyse dynamique.
## Fuzzing des schémas d'URL
Si l'application analyse des parties de l'URL, vous pouvez également effectuer un fuzzing d'entrée pour détecter des bugs de corruption de mémoire.
Ce que nous avons appris ci-dessus peut maintenant être utilisé pour construire votre propre fuzzer dans le langage de votre choix, par exemple en Python, et appeler `openURL` en utilisant [RPC de Frida](https://www.frida.re/docs/javascript-api/#rpc). Ce fuzzer doit faire ce qui suit :
* Générer des charges utiles.
* Pour chacun d'eux, appeler `openURL`.
* Vérifier si l'application génère un rapport de plantage (`.ips`) dans `/private/var/mobile/Library/Logs/CrashReporter`.
Le projet [FuzzDB](https://github.com/fuzzdb-project/fuzzdb) propose des dictionnaires de fuzzing que vous pouvez utiliser comme charges utiles.
## **Fuzzing avec Frida**
Faire cela avec Frida est assez facile, vous pouvez vous référer à ce [blog post](https://grepharder.github.io/blog/0x03\_learning\_about\_universal\_links\_and\_fuzzing\_url\_schemes\_on\_ios\_with\_frida.html) pour voir un exemple qui fuzzes l'application iGoat-Swift (fonctionnant sur iOS 11.1.2).
Avant d'exécuter le fuzzer, nous avons besoin des schémas d'URL en tant qu'entrées. À partir de l'analyse statique, nous savons que l'application iGoat-Swift prend en charge le schéma d'URL et les paramètres suivants : `iGoat://?contactNumber={0}&message={0}`.
```bash
$ 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
```
# Références
{% embed url="https://mobile-security.gitbook.io/mobile-security-testing-guide/ios-testing-guide/0x06h-testing-platform-interaction#testing-object-persistence-mstg-platform-8" %}
<details>
<summary><a href="https://cloud.hacktricks.xyz/pentesting-cloud/pentesting-cloud-methodology"><strong>☁️ HackTricks Cloud ☁️</strong></a> -<a href="https://twitter.com/hacktricks_live"><strong>🐦 Twitter 🐦</strong></a> - <a href="https://www.twitch.tv/hacktricks_live/schedule"><strong>🎙️ Twitch 🎙️</strong></a> - <a href="https://www.youtube.com/@hacktricks_LIVE"><strong>🎥 Youtube 🎥</strong></a></summary>
- Travaillez-vous dans une entreprise de **cybersécurité** ? Voulez-vous voir votre **entreprise annoncée dans HackTricks** ? ou voulez-vous avoir accès à la **dernière version de PEASS ou télécharger HackTricks en PDF** ? Consultez les [**PLANS D'ABONNEMENT**](https://github.com/sponsors/carlospolop) !
- Découvrez [**The PEASS Family**](https://opensea.io/collection/the-peass-family), notre collection exclusive de [**NFTs**](https://opensea.io/collection/the-peass-family)
- Obtenez le [**swag officiel PEASS & HackTricks**](https://peass.creator-spring.com)
- **Rejoignez le** [**💬**](https://emojipedia.org/speech-balloon/) [**groupe Discord**](https://discord.gg/hRep4RUj7f) ou le [**groupe telegram**](https://t.me/peass) ou **suivez** moi sur **Twitter** [**🐦**](https://github.com/carlospolop/hacktricks/tree/7af18b62b3bdc423e11444677a6a73d4043511e9/\[https:/emojipedia.org/bird/README.md)[**@carlospolopm**](https://twitter.com/hacktricks_live)**.**
- **Partagez vos astuces de piratage en soumettant des PR au [repo hacktricks](https://github.com/carlospolop/hacktricks) et au [repo hacktricks-cloud](https://github.com/carlospolop/hacktricks-cloud)**.
</details>