hacktricks/mobile-pentesting/ios-pentesting/ios-custom-uri-handlers-deeplinks-custom-schemes.md

13 KiB
Raw Blame History

零基础学习AWS黑客攻击直至成为专家 htARTE (HackTricks AWS红队专家)

支持HackTricks的其他方式

自定义URL方案允许应用程序通过自定义协议进行通信。应用程序必须声明对方案的支持并处理使用这些方案的传入URL。

URL方案为您的应用程序提供了潜在的攻击途径因此请确保验证所有URL参数丢弃任何格式不正确的URL。此外,限制可用的操作,以避免风险用户数据

例如URImyapp://hostname?data=123876123调用 应用程序 mydata注册方案mydata的那个)执行与主机名hostname相关的操作,发送参数data,其值为123876123

一个脆弱的例子是以下2010年发现的Skype移动应用程序中的漏洞Skype应用程序注册了skype://协议处理程序,允许其他应用程序触发对其他Skype用户和电话号码的呼叫。不幸的是Skype在拨打电话前没有请求用户的许可因此任何应用程序都可以在不知情的情况下呼叫任意号码。攻击者通过在恶意网站上放置一个不可见的<iframe src="skype://xxx?call"></iframe>(其中xxx被替换为高价号码因此任何无意中访问该网站的Skype用户都会呼叫高价号码。

您可以在应用程序的**Info.plist文件中找到应用程序注册的方案**,搜索**CFBundleURLTypes**(来自iGoat-Swift的示例):

<key>CFBundleURLTypes</key>
<array>
<dict>
<key>CFBundleURLName</key>
<string>com.iGoat.myCompany</string>
<key>CFBundleURLSchemes</key>
<array>
<string>iGoat</string>
</array>
</dict>
</array>

然而,请注意,恶意应用程序可以重新注册已由应用程序注册的URI。因此如果您通过URI发送敏感信息myapp://hostname?password=123456一个恶意应用程序可以拦截带有敏感信息的URI。

此外这些URI的输入应该被检查和清理因为它可能来自试图利用SQL注入、XSS、CSRF、路径遍历或其他可能的漏洞的恶意来源。

应用程序查询方案注册

应用程序可以调用canOpenURL:来验证目标应用程序是否可用。然而,由于这种方法被恶意应用程序用作枚举已安装应用程序的方式,从iOS 9.0开始传递给它的URL方案也必须通过在应用程序的Info.plist文件中添加LSApplicationQueriesSchemes键并声明一个最多50个URL方案的数组来声明

<key>LSApplicationQueriesSchemes</key>
<array>
<string>url_scheme1</string>
<string>url_scheme2</string>
</array>

canOpenURL 将始终为未声明的方案返回 NO,无论是否安装了适当的应用程序。然而,这个限制仅适用于 canOpenURL

测试 URL 处理和验证

为了确定 URL 路径是如何构建和验证的,如果您有原始源代码,您可以搜索以下方法

  • application:didFinishLaunchingWithOptions: 方法或 application:will-FinishLaunchingWithOptions::验证决策是如何做出的以及 URL 信息是如何检索的。
  • application:openURL:options::验证资源是如何被打开的,即数据是如何被解析的,验证 options,特别是是否应该允许或拒绝调用应用程序(sourceApplication)的访问。应用程序在使用自定义 URL 方案时也可能需要用户权限。

在 Telegram 中,您将发现有四种不同的方法被使用

func application(_ application: UIApplication, open url: URL, sourceApplication: String?) -> Bool {
self.openUrl(url: url)
return true
}

func application(_ application: UIApplication, open url: URL, sourceApplication: String?,
annotation: Any) -> Bool {
self.openUrl(url: url)
return true
}

func application(_ app: UIApplication, open url: URL,
options: [UIApplicationOpenURLOptionsKey : Any] = [:]) -> Bool {
self.openUrl(url: url)
return true
}

func application(_ application: UIApplication, handleOpen url: URL) -> Bool {
self.openUrl(url: url)
return true
}

测试对其他应用的 URL 请求

方法 openURL:options:completionHandler:已弃用的 UIApplicationopenURL: 方法 负责打开 URLs(即向其他应用发送请求/进行查询),这些请求可能是当前应用本地的,也可能需要由不同的应用提供。如果你有原始源代码,你可以直接搜索这些方法的使用情况。

此外,如果你有兴趣了解应用是否正在查询特定的服务或应用,以及该应用是否众所周知,你也可以在线搜索常见的 URL 方案,并将它们包含在你的grepsiOS 应用方案列表****中。

egrep -nr "open.*options.*completionHandler" ./Telegram-iOS/
egrep -nr "openURL\(" ./Telegram-iOS/
egrep -nr "mt-encrypted-file://" ./Telegram-iOS/
egrep -nr "://" ./Telegram-iOS/

测试已弃用的方法

搜索已弃用的方法,例如:

例如,这里我们找到了这三个:

$ rabin2 -zzq Telegram\ X.app/Telegram\ X | grep -i "openurl"

0x1000d9e90 31 30 UIApplicationOpenURLOptionsKey
0x1000dee3f 50 49 application:openURL:sourceApplication:annotation:
0x1000dee71 29 28 application:openURL:options:
0x1000dee8e 27 26 application:handleOpenURL:
0x1000df2c9 9 8 openURL:
0x1000df766 12 11 canOpenURL:
0x1000df772 35 34 openURL:options:completionHandler:
...

调用任意 URLs

  • Safari: 要快速测试一个 URL 方案,你可以在 Safari 中打开 URLs 并观察应用程序的行为。例如,如果你写入 tel://123456789Safari 将尝试开始拨打该号码。
  • Notes App: 长按你写入的链接以测试自定义 URL 方案。记得退出编辑模式以便能够打开它们。请注意,只有当应用程序安装后,你才能点击或长按包含自定义 URL 方案的链接,否则它们不会被突出显示为 可点击链接
  • IDB:
  • 启动 IDB连接到你的设备并选择目标应用程序。你可以在 IDB 文档中找到详细信息。
  • 转到 URL Handlers 部分。在 URL 方案 中,点击 Refresh,在左侧你会找到正在测试的应用程序中定义的所有自定义方案的列表。你可以通过点击右侧的 Open 来加载这些方案。通过简单地打开一个空白的 URI 方案(例如,打开 myURLscheme://),你可以发现隐藏的功能(例如,调试窗口)并绕过本地认证。
  • Frida:

如果你只是想打开 URL 方案,你可以使用 Frida 来做到这一点:

$ frida -U iGoat-Swift

[iPhone::iGoat-Swift]-> function openURL(url) {
var UIApplication = ObjC.classes.UIApplication.sharedApplication();
var toOpen = ObjC.classes.NSURL.URLWithString_(url);
return UIApplication.openURL_(toOpen);
}
[iPhone::iGoat-Swift]-> openURL("tel://234234234")
true

在这个来自 Frida CodeShare 的例子中,作者使用了非公开 API LSApplicationWorkspace.openSensitiveURL:withOptions: 来打开 URLs来自 SpringBoard 应用程序):

function openURL(url) {
var w = ObjC.classes.LSApplicationWorkspace.defaultWorkspace();
var toOpen = ObjC.classes.NSURL.URLWithString_(url);
return w.openSensitiveURL_withOptions_(toOpen, null);
}

请注意,在 App Store 上不允许使用非公开 API这就是为什么我们甚至不测试这些但我们被允许在我们的动态分析中使用它们。

Fuzzing URL 方案

如果应用程序解析 URL 的部分内容,你也可以执行输入 fuzzing 来检测内存损坏错误。

我们上面学到的现在可以用来构建你自己的 fuzzer使用你选择的语言例如 Python并使用 Frida 的 RPC 调用 openURL。该 fuzzer 应该执行以下操作:

  • 生成有效载荷。
  • 对每个有效载荷调用 openURL
  • 检查应用程序是否在 /private/var/mobile/Library/Logs/CrashReporter 生成崩溃报告(.ips)。

FuzzDB 项目提供了你可以用作有效载荷的 fuzzing 字典。

使用 Frida 进行 Fuzzing

使用 Frida 进行这项操作非常简单,你可以参考这篇 博客文章 查看一个对 iGoat-Swift 应用程序进行 fuzzing 的例子(在 iOS 11.1.2 上运行)。

在运行 fuzzer 之前,我们需要 URL 方案作为输入。从静态分析我们知道 iGoat-Swift 应用程序支持以下 URL 方案和参数:iGoat://?contactNumber={0}&message={0}

$ frida -U SpringBoard -l ios-url-scheme-fuzzing.js
[iPhone::SpringBoard]-> fuzz("iGoat", "iGoat://?contactNumber={0}&message={0}")
Watching for crashes from iGoat...
No logs were moved.
Opened URL: iGoat://?contactNumber=0&message=0

参考资料

{% embed url="https://mobile-security.gitbook.io/mobile-security-testing-guide/ios-testing-guide/0x06h-testing-platform-interaction#testing-object-persistence-mstg-platform-8" %}

从零开始学习AWS黑客技术成为 htARTE (HackTricks AWS Red Team Expert)

支持HackTricks的其他方式