跳过内容

MASTG-TEST-0076: 测试 iOS WebView

此测试即将更新

此测试目前可使用,但将作为新的 OWASP MASTG v2 指南 的一部分进行全面修订。

通过提交 PR 来帮助我们:MASTG v1->v2 MASTG-TEST-0076: 测试 iOS WebViews (ios)

发送反馈

概述

静态分析

对于静态分析,我们将主要关注以下几点,并将 UIWebViewWKWebView 纳入范围。

  • 识别 WebView 使用情况
  • 测试 JavaScript 是否启用
  • 测试混合内容
  • 测试 WebView URI 操作

识别 WebView 使用情况

通过在 Xcode 中搜索来查找上述 WebView 类的用法。

在编译后的二进制文件中,您可以在其符号或字符串中搜索,例如使用 rabin2 像这样

UIWebView

$ 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

$ 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

或者,您也可以搜索这些 WebView 类的已知方法。例如,搜索用于初始化 WKWebView 的方法 (init(frame:configuration:))

$ 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

您也可以 demangle 它

$ xcrun swift-demangle __T0So9WKWebViewCABSC6CGRectV5frame_So0aB13ConfigurationC13configurationtcfcTO

---> @nonobjc __C.WKWebView.init(frame: __C_Synthesized.CGRect,
                                configuration: __C.WKWebViewConfiguration) -> __C.WKWebView

测试 JavaScript 是否启用

首先,请记住,对于 UIWebView,JavaScript 无法禁用。

对于 WKWebView,作为最佳实践,除非明确要求,否则应禁用 JavaScript。要验证 JavaScript 是否已正确禁用,请在项目中搜索 WKPreferences 的用法,并确保 javaScriptEnabled 属性设置为 false

let webPreferences = WKPreferences()
webPreferences.javaScriptEnabled = false

如果只有编译后的二进制文件,您可以使用 rabin2 在其中搜索。

$ 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:

如果定义了用户脚本,它们将继续运行,因为 javaScriptEnabled 属性不会影响它们。有关将用户脚本注入 WKWebViews 的更多信息,请参见 WKUserContentControllerWKUserScript

测试混合内容

UIWebView 不同,使用 WKWebView 时,可以检测 混合内容(从 HTTPS 页面加载的 HTTP 内容)。通过使用方法 hasOnlySecureContent,可以验证页面上的所有资源是否都已通过安全加密的连接加载。来自 [#thiel2] 的这个示例(请参见第 159 页和 160 页)使用此方法来确保仅将通过 HTTPS 加载的内容显示给用户,否则会显示警报,告知用户检测到混合内容。

在编译后的二进制文件中,您可以使用 rabin2

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

# nothing found

在这种情况下,该应用程序没有利用这一点。

此外,如果您有原始源代码或 IPA,则可以检查嵌入的 HTML 文件并验证它们是否不包含混合内容。在源代码中和标签属性中搜索 http://,但请记住,这可能会给出误报,例如,找到一个包含 http:// 在其 href 属性中的锚标记 <a> 并不总是表示混合内容问题。在 MDN Web Docs 中了解有关混合内容的更多信息。

测试 WebView URI 操作

确保用户的 WebView URI 不能被操作,以便加载 WebView 功能不需要的其他类型的资源。当 WebView 的内容从本地文件系统加载时,这可能会特别危险,允许用户导航到应用程序中的其他资源。

动态分析

对于动态分析,我们将解决静态分析中的相同点。

  • 枚举 WebView 实例
  • 测试 JavaScript 是否启用
  • 测试混合内容

通过执行动态检测,可以识别 WebView 并在运行时获取其所有属性。当您没有原始源代码时,这非常有用。

对于以下示例,我们将继续使用 "Where's My Browser?" 应用程序和 Frida REPL。

枚举 WebView 实例

一旦您在应用程序中识别出一个 WebView,您可以检查堆以查找我们在上面看到的一个或多个 WebViews 的实例。

例如,如果您使用 Frida,您可以通过 "ObjC.choose()" 检查堆来做到这一点

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

对于 UIWebViewWKWebView WebViews,为了完整起见,我们还打印相关的 URL。

为了确保您能够在堆中找到 WebViews 的实例,请务必首先导航到您找到的 WebView。到那里后,运行上面的代码,例如,通过复制到 Frida REPL

$ frida -U com.authenticationfailure.WheresMyBrowser

# copy the code and wait ...

onMatch:  <UIWebView: 0x14fd25e50; frame = (0 126; 320 393);
                autoresize = RM+BM; layer = <CALayer: 0x1c422d100>>
URL:  <NSMutableURLRequest: 0x1c000ef00> {
  URL: file:///var/mobile/Containers/Data/Application/A654D169-1DB7-429C-9DB9-A871389A8BAA/
          Library/UIWebView/scenario1.html, Method GET, Headers {
    Accept =     (
        "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8"
    );
    "Upgrade-Insecure-Requests" =     (
        1
    );
    "User-Agent" =     (
        "Mozilla/5.0 (iPhone; CPU iPhone ... AppleWebKit/604.3.5 (KHTML, like Gecko) Mobile/..."
    );
} }

现在我们用 q 退出并打开另一个 WebView(在本例中为 WKWebView)。如果我们重复之前的步骤,它也会被检测到

$ frida -U com.authenticationfailure.WheresMyBrowser

# copy the code and wait ...

onMatch:  <WKWebView: 0x1508b1200; frame = (0 0; 320 393); layer = <CALayer: 0x1c4238f20>>
URL:  file:///var/mobile/Containers/Data/Application/A654D169-1DB7-429C-9DB9-A871389A8BAA/
            Library/WKWebView/scenario1.html

我们将在以下各节中扩展此示例,以便从 WebViews 获取更多信息。我们建议将此代码存储到一个文件中,例如 webviews_inspector.js,并像这样运行它

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

检查 JavaScript 是否启用

请记住,如果正在使用 UIWebView,则默认启用 JavaScript,并且无法禁用它。

对于 WKWebView,您应该验证是否启用了 JavaScript。为此,请使用来自 WKPreferencesjavaScriptEnabled

使用以下行扩展先前的脚本

ObjC.choose(ObjC.classes['WKWebView'], {
  onMatch: function (wk) {
    console.log('onMatch: ', wk);
    console.log('javaScriptEnabled:', wk.configuration().preferences().javaScriptEnabled());
//...
  }
});

输出现在显示,实际上,JavaScript 已启用

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

onMatch:  <WKWebView: 0x1508b1200; frame = (0 0; 320 393); layer = <CALayer: 0x1c4238f20>>

javaScriptEnabled:  true

测试混合内容

UIWebView 类不提供用于验证是否仅允许安全内容的方法。但是,从 iOS 10 开始Upgrade-Insecure-Requests CSP(内容安全策略)指令已引入 WebKit,这是为 iOS WebViews 提供支持的浏览器引擎。此指令可用于指示浏览器将不安全的请求升级为安全的请求。这是防止混合内容问题的一个好方法。

对于 WKWebView's,您可以为堆中找到的每个 WKWebView 调用方法 hasOnlySecureContent。请记住在 WebView 加载后执行此操作。

使用以下行扩展先前的脚本

ObjC.choose(ObjC.classes['WKWebView'], {
  onMatch: function (wk) {
    console.log('onMatch: ', wk);
    console.log('hasOnlySecureContent: ', wk.hasOnlySecureContent().toString());
    //...
      }
    });

输出显示页面上的一些资源已通过不安全的连接加载

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

onMatch:  <WKWebView: 0x1508b1200; frame = (0 0; 320 393); layer = <CALayer: 0x1c4238f20>>

hasOnlySecureContent:  false