Bug Bounty Patterns 2024-2026 — ios-pentest
Overview
Post-2023 iOS bug-bounty patterns covering custom-URL-scheme / Universal-Link hijacking,
WebView injection via deep-link parameters (iOS variant), and insecure Keychain storage
of IAM / cloud tokens. Sources: 8kSec iOS deep-link research 2024, Apple AASA docs,
AWS/Azure mobile SDK 2024-2025 audits. Last validated: 2026-04.
Emit findings via ../schemas/finding.json.
Pattern Index
| # | Pattern | Severity | Primary Source |
|---|---|---|---|
| P35 | URL-scheme / Universal-Link hijacking and AASA bypass | Critical | 8kSec 2024 · Apple docs |
| P36b | WebView XSS via unsafe deep-link URL loading (iOS) | Critical | 8kSec 2024-2025 |
| P38 | Keychain insecurity — IAM / cloud tokens stored plainly | Critical | AWS/Azure mobile SDK audits 2024-2025 |
Patterns
P35. URL-Scheme / Universal-Link Hijacking and AASA Bypass
- CVE / Source: 8kSec "iOS Deeplink Attacks" part 1 & 2 (2024); Apple AASA documentation.
- Summary: (a) Two apps can register the same
CFBundleURLSchemesentry — iOS gives precedence by install order and there is no user-visible warning; (b) Universal Links are only enforced if theapple-app-site-associationfile is reachable, returns correct Content-Type, and its paths are scoped — misconfiguration collapses back to Safari; (c) AASA caching means revocation is often delayed. - Affected surface: Info.plist
CFBundleURLTypeswithout ownership check; Universal-Link handlers that accept any path under the domain; apps that skipcontinueUserActivityvalidation. - Detection (automated):
Red flags: AASA not served over HTTPS, wrong Content-Type (# Static: extract scheme / UL info otool -l App.app/App | grep -A4 "LC_CFBUNDLE" plistutil -i App.app/Info.plist -f xml | python3 -c ' import sys, plistlib p = plistlib.loads(sys.stdin.buffer.read()) print("URLSchemes:", [t for u in p.get("CFBundleURLTypes", []) for t in u.get("CFBundleURLSchemes", [])]) print("AssociatedDomains:", p.get("com.apple.developer.associated-domains"))' # AASA validation curl -sSL https://domain/.well-known/apple-app-site-association | jq . curl -sSL https://domain/apple-app-site-association | jq .application/pkcs7-mimerequired on older iOS), wildcard path"/*", missingappIDsentries. - Exploitation / PoC: Register a malicious profile that claims the same scheme; publish an app via TestFlight with the matching Info.plist; iOS allows both — the later installed can win. For UL bypass: seed a link into Mail/Safari; if the app isn't registered correctly, the link falls back to a website the attacker owns.
- Indicators: AASA file served with wrong MIME; app receives
openURLfrom scheme it believes only it owns; OAuthcodedelivered to unexpected bundle-id. - Mitigation: Prefer Universal Links over custom schemes; tight AASA with
paths: [ "NOT /oauth/*", "/known/*" ]; enforce server-side nonce; inapplication(_:continue:restorationHandler:)verifyNSUserActivity.webpageURLhost. - Cross-refs: MASTG-TEST-0065; CWE-926, CWE-927; related → P36b, Android P34.
P36b. WebView XSS via Unsafe Deep-Link URL Loading (iOS)
- CVE / Source: 8kSec iOS WebView security research 2024-2025.
- Summary:
WKWebView/ legacyUIWebViewfed with deep-link URLs render attacker-controlled HTML; JS bridges (WKScriptMessageHandler,JSContext, Cordova/Capacitor plugins) become RCE surfaces when injected payloads invoke exported methods. - Affected surface: In-app browsers; help/promo pages; hybrid apps (Ionic, Cordova, Capacitor, React-Native WebView);
javaScriptEnabled == truewith exposed handlers. - Detection (automated):
# Static: scan Swift / Obj-C for sinks ripgrep -n 'loadHTMLString|WKUserContentController|addScriptMessageHandler|evaluateJavaScript' Source/ # Dynamic: Frida / objection objection -g "Victim" explore ios webview dump # Fire the deep link: xcrun simctl openurl booted 'victim://browse?url=javascript:window.webkit.messageHandlers.bridge.postMessage("leak")' - Exploitation / PoC:
// Vulnerable: deep-link -> openURL -> webView.load(URLRequest(url: url)) let url = notification.userInfo?["url"] as! URL self.webView.load(URLRequest(url: url)) - Indicators: WebView renders
data:/javascript:URLs sourced from Intent/URL schemes; bridge messages fired without user interaction. - Mitigation: Scheme allow-list (
httpsonly); validate host against AASA list; restrict bridge to idempotent methods;configuration.websiteDataStore = .nonPersistent(); disable JS if not needed. - Cross-refs: MASTG-TEST-0069; CWE-79; related → P35, Android P36a.
P38. Keychain Insecurity — IAM / Cloud Tokens Stored Plainly
- CVE / Source: AWS Amplify / Azure MSAL / Firebase iOS SDK audits 2024-2025; repeated HackerOne writeups.
- Summary: Apps store long-lived IAM tokens (Cognito refresh, Azure AD refresh, Firebase refresh) in Keychain items without
kSecAttrAccessibleset restrictively (kSecAttrAccessibleWhenUnlockedThisDeviceOnly) or without biometric ACL; tokens leak via iTunes backups, iCloud keychain sync, or jailbreak file-system dump. - Affected surface: iOS apps with cloud / SaaS SSO; React-Native apps using
react-native-keychainwith defaults; Xamarin bridges that fall back to NSUserDefaults. - Detection (automated):
# Static hunt ripgrep -n 'kSecAttrAccessible|SecItemAdd|SecItemCopyMatching|kSecAttrAccessControl' Source/ # Dynamic with objection objection -g "Victim" explore ios keychain dump # Look for tokens, refresh_tokens, AWS credentials - Exploitation / PoC: On a jailbroken / dev device, dump Keychain and inspect item for
kSecAttrAccessibleAlways→ credential re-usable off-device. Or: inspect.ipabackup from unencrypted iTunes backup. - Indicators: Keychain items with
Alwaysaccessibility; refresh tokens present in backup; absence ofSecAccessControlwith biometric policy. - Mitigation:
kSecAttrAccessibleWhenUnlockedThisDeviceOnly;SecAccessControlCreateWithFlags(.biometryCurrentSet | .userPresence); bind tokens to device via attestation (DCAppAttestService); exclude from backup (NSURLIsExcludedFromBackupKey); rotate refresh tokens. - Cross-refs: MASTG-TEST-0054; CWE-522, CWE-312; related → API P4.
Payload catalog additions
See ../payloads/url_scheme_tests.txt — appended with Universal-Link bypass and AASA-mismatch vectors.
Cross-skill links
- Android: P34/P36a/P37 counterparts —
../../android-pentest/references/bounty_patterns_2024_2026.md. - API: refresh-token persistence (P4) —
../../api-security/methodology/bounty_patterns_2024_2026.md. - Cloud: Cognito / Azure AD misconfig chains —
../../cloud-security/references/bounty_patterns_2024_2026.md.