Post

TrustFall - 8kSec


Description:

TrustFall is a secure iOS workspace app that uses deep linking to load trusted content inside an embedded browser. It claims to only open links from approved domains, but its defenses aren’t as strong as they seem. Direct access to untrusted domains is blocked unless you find a loophole.


Objective:

  • Find a way to trick the app into loading an unintended URL and triggering the hidden flag.
  • Use deep link manipulation to bypass the app’s domain filtering and get it to load a crafted URL.


Explore the application

When the app launches, it displays a screen with three buttons, but none of them perform any actions.


From the Info.plist file, this entry registers the app to automatically launch whenever a URL beginning with trustfall:// is opened.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
└─# ipsw plist Info.plist                
{
  "BuildMachineOSBuild": "24D70",
  "CFBundleDevelopmentRegion": "en",
  "CFBundleExecutable": "TrustFall",
  "CFBundleURLTypes": [
    {
      "CFBundleTypeRole": "Editor",
      "CFBundleURLName": "trustfall",
      "CFBundleURLSchemes": [
        "trustfall"
      ]
    }
  ],


Reverse Engineering With Ghidra

the function _$s9TrustFall11ContentViewV17handleIncomingURLyy10Foundation0G0VF When demangled, this becomes:

1
TrustFall.ContentView.handleIncomingURL(_ url: Foundation.URL)


This function handles URLs that the app receives (via a deep link)


It Checks if the URL’s scheme equals "trustfall".



Then checks if the host equals "open".


It parses the URL’s query parameters and verifies whether the resulting URL begins with https://8ksec.io.



If the domain matches "8ksec.io", the app updates its SwiftUI states as expected. Otherwise, it changes its internal state to display the flag, indicating that an unsafe or modified URL was detected.


StepActionDescription
1Extract URL schemeOnly process URLs with the scheme "trustfall".
2Extract hostOnly handle URLs where host is "open".
3Parse query parametersUse URLComponents to parse key–value pairs from the query string.
4Find a specific query itemLooks for a certain query (maybe ?url= or similar).
5Create a new URL from that query valueAttempt to sanitize or validate it.
6Check if the new URL starts with "https://8ksec.io"Trusted domain check.
7If trustedLoad the URL into SwiftUI’s state.
8If not trustedSet a SwiftUI state to display "CTF{bad_url_sanitization}".


If you open the deeplink trustfall://open?url=https://8ksec.io, the app will load the https://8ksec.io website within its embedded browser.

1
trustfall://open?url=https://8ksec.io



This Frida script watches whenever the app’s web view (WKWebView) loads a web page. Each time it happens, it logs the exact URL the app is trying to load.

1
2
3
4
5
6
7
Interceptor.attach(ObjC.classes.WKWebView["- loadRequest:"].implementation, {
    onEnter(args) {
        const req = new ObjC.Object(args[2]);
        const url = req.URL().absoluteString();
        console.log("[WKWebView] Loading URL:", url.toString());
    }
});

Run the app with this Frida script, open the deeplink, and you’ll see the script log that it’s opening the URL:

1
[iOS Device::com.8ksec.TrustFall.W46SY5ZJ6Z ]-> [WKWebView] Loading URL: https://8ksec.io


Because the app only tests whether the URL string starts with "https://8ksec.io", that check is too weak and can be bypassed by URLs where 8ksec.io is merely part of a larger hostname or a subdomain of another domain. For example:

1
2
3
trustfall://open?url=https://8ksec.io.google.com
trustfall://open?url=https://8ksec.iogoogle.com
trustfall://open?url=https://8ksec.io.com


If you open the deeplink trustfall://open?url=https://8ksec.io.google.com, the app will attempt to load https://8ksec.io.google.com. And because that site does not exist, the embedded browser will display a blank page.

1
trustfall://open?url=https://8ksec.io.google.com


1
[iOS Device::com.8ksec.TrustFall.W46SY5ZJ6Z ]-> [WKWebView] Loading URL: https://8ksec.io.google.com



If the URL isn’t trusted (doesn’t start with https://8ksec.io), the app displays an alert “Suspicious Activity Detected” and shows the challenge flag.




To retrieve the flag, open a URL that is not trusted (it does not start with https://8ksec.io) but whose host contains 8ksec.io. Examples:

1
2
3
trustfall://open?url=http://8ksec.io
trustfall://open?url=http://8ksec.io.com
trustfall://open?url=any://8ksec.iogoogle.com



Flag: CTF{bad_url_sanitization}


Note: On smaller iPhones (e.g., iPhone 7, 8, X), the flag might not be visible because it appears at the bottom of the screen and can be hidden due to the limited display size. To see the flag, use a larger iPhone model (e.g., iPhone 7 Plus, 8 Plus, or any Pro/Pro Max models).

This post is licensed under CC BY 4.0 by the author.