跳过内容

MASTG-TEST-0069: 测试应用权限

此测试即将更新

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

请提交 PR 来帮助我们完成以下内容:MASTG v1->v2 MASTG-TEST-0069:测试应用权限 (ios)

发送反馈

概述

静态分析

自从 iOS 10 以来,以下是您需要检查权限的主要区域:

  • Info.plist 文件中的用途字符串
  • 代码签名权限文件
  • 嵌入式 Provisioning Profile 文件
  • 编译后的应用二进制文件中嵌入的权限
  • 源代码中权限的使用

Info.plist 文件中的用途字符串

如果拥有原始源代码,则可以验证 Info.plist 文件中包含的权限

  • 使用 Xcode 打开项目。
  • 在默认编辑器中查找并打开 Info.plist 文件,然后搜索以 "Privacy -" 开头的键。

您可以切换视图以显示原始值,方法是右键单击并选择“显示原始键/值”(例如,这样 "Privacy - Location When In Use Usage Description" 将变为 NSLocationWhenInUseUsageDescription)。

如果只有 IPA

  • 解压缩 IPA。
  • Info.plist 位于 Payload/<appname>.app/Info.plist 中。
  • 如果需要,请转换它(例如,plutil -convert xml1 Info.plist),如“iOS 基本安全测试”一章的“Info.plist 文件”部分所述。
  • 检查所有*用途字符串 Info.plist 键*,通常以 UsageDescription 结尾

    <plist version="1.0">
    <dict>
        <key>NSLocationWhenInUseUsageDescription</key>
        <string>Your location is used to provide turn-by-turn directions to your destination.</string>
    

对于 Info.plist 文件中的每个用途字符串,检查该权限是否有意义。

例如,假设以下几行是从 Solitaire 游戏使用的 Info.plist 文件中提取的

<key>NSHealthClinicalHealthRecordsShareUsageDescription</key>
<string>Share your health data with us!</string>
<key>NSCameraUsageDescription</key>
<string>We want to access your camera</string>

一个普通的纸牌游戏请求这种资源访问应该是可疑的,因为它可能不需要访问相机用户的健康记录

除了简单地检查权限是否有意义之外,还可以通过分析用途字符串来得出进一步的分析步骤,例如,它们是否与存储敏感数据有关。例如,NSPhotoLibraryUsageDescription 可以被视为存储权限,授予对应用程序沙箱之外的文件的访问权限,并且可能也可以被其他应用程序访问。在这种情况下,应测试是否没有在那里存储敏感数据(在这种情况下为照片)。对于其他用途字符串,例如 NSLocationAlwaysUsageDescription,还必须考虑应用程序是否安全地存储此数据。有关安全存储敏感数据的更多信息和最佳实践,请参阅“测试数据存储”一章。

嵌入式 Provisioning Profile 文件

当您没有原始源代码时,您应该分析 IPA 并在其中搜索*嵌入式 Provisioning Profile*,该文件通常位于根应用程序 bundle 文件夹 (Payload/<appname>.app/) 中,名称为 embedded.mobileprovision

此文件不是 .plist,而是使用加密消息语法进行编码的。在 macOS 上,您可以使用以下命令检查嵌入式 Provisioning Profile 的权限

security cms -D -i embedded.mobileprovision

然后搜索权限键区域 (<key>Entitlements</key>)。

编译后的应用二进制文件中嵌入的权限

如果您只有应用程序的 IPA,或者只是在越狱设备上安装的应用程序,通常您将无法找到 .entitlements 文件。embedded.mobileprovision 文件也可能是这种情况。但是,您仍然应该能够从应用程序二进制文件中提取权限属性列表(请参阅* 从 MachO 二进制文件中提取权限*)。

源代码中权限的使用

检查完 <appname>.entitlements 文件和 Info.plist 文件后,就该验证所请求的权限和分配的权限的实际使用方式了。为此,源代码审查应该足够了。但是,如果您没有原始源代码,则验证权限的使用可能特别具有挑战性,因为您可能需要对应用程序进行逆向工程,有关如何继续操作的更多详细信息,请参阅“动态分析”。

在进行源代码审查时,请注意

  • Info.plist 文件中的*用途字符串*是否与程序实现匹配。
  • 注册的功能是否以不会泄漏机密信息的方式使用。

用户可以随时通过“设置”授予或撤销授权,因此应用程序通常在访问功能之前检查该功能的授权状态。这可以通过使用专用的 API 来完成,这些 API 适用于许多系统框架,这些框架提供对受保护资源的访问。

您可以使用Apple 开发者文档作为起点。例如

  • 蓝牙:state属性的 CBCentralManager 类用于检查使用蓝牙外围设备 的系统授权状态。
  • 位置:搜索 CLLocationManager 的方法,例如 locationServicesEnabled

    func checkForLocationServices() {
        if CLLocationManager.locationServicesEnabled() {
            // Location services are available, so query the user’s location.
        } else {
            // Update your app’s UI to show that the location is unavailable.
        }
    }
    

    有关完整列表,请参阅 “确定位置服务的可用性”(Apple 开发者文档)中的表 1。

浏览应用程序,搜索这些 API 的用法,并检查可能从这些 API 获得敏感数据会发生什么。例如,它可能会存储或通过网络传输,如果是这种情况,则应额外验证适当的数据保护和传输安全性。

动态分析

借助静态分析,您应该已经有一个正在使用的包含权限和应用程序功能列表。但是,如“源代码检查”中所述,当您没有原始源代码时,发现敏感数据和与这些权限和应用程序功能相关的 API 可能是一项具有挑战性的任务。动态分析可以帮助在这里获取输入,以便迭代到静态分析中。

遵循如下所示的方法应该可以帮助您发现提到的敏感数据和 API

  1. 考虑在静态分析中标识的权限/功能列表(例如 NSLocationWhenInUseUsageDescription)。
  2. 将它们映射到相应系统框架的专用 API(例如 Core Location)。您可以使用Apple 开发者文档 来实现此目的。
  3. 跟踪这些 API 的类或特定方法(例如 CLLocationManager),例如,使用frida-trace
  4. 确定应用程序在访问相关功能(例如“共享您的位置”)时真正使用哪些方法。
  5. 获取这些方法的回溯并尝试构建调用图。

一旦识别出所有方法,您可以使用这些知识来对应用程序进行逆向工程,并尝试找出数据的处理方式。在执行此操作时,您可能会发现过程中涉及的新方法,您可以再次将其提供给上面的步骤 3,并在静态分析和动态分析之间保持迭代。

在以下示例中,我们使用 Telegram 从聊天中打开共享对话框,并使用 frida-trace 识别正在调用的方法。

首先,我们启动 Telegram 并开始跟踪与字符串“authorizationStatus”匹配的所有方法(这是一种通用方法,因为除了 CLLocationManager 之外的更多类都实现了此方法)

frida-trace -U "Telegram" -m "*[* *authorizationStatus*]"

-U 连接到 USB 设备。-m 将 Objective-C 方法包含到跟踪中。您可以使用 glob 模式(例如,使用“*”通配符,-m "*[* *authorizationStatus*]" 表示“包含任何包含 'authorizationStatus' 的类的任何 Objective-C 方法”)。键入 frida-trace -h 以获取更多信息。

现在我们打开共享对话框

将显示以下方法

  1942 ms  +[PHPhotoLibrary authorizationStatus]
  1959 ms  +[TGMediaAssetsLibrary authorizationStatusSignal]
  1959 ms     | +[TGMediaAssetsModernLibrary authorizationStatusSignal]

如果我们单击位置,将跟踪另一个方法

 11186 ms  +[CLLocationManager authorizationStatus]
 11186 ms     | +[CLLocationManager _authorizationStatus]
 11186 ms     |    | +[CLLocationManager _authorizationStatusForBundleIdentifier:0x0 bundle:0x0]

使用 frida-trace 的自动生成的存根来获取更多信息,例如返回值和回溯。对以下 JavaScript 文件进行以下修改(路径相对于当前目录)

// __handlers__/__CLLocationManager_authorizationStatus_.js

  onEnter: function (log, args, state) {
    log("+[CLLocationManager authorizationStatus]");
    log("Called from:\n" +
        Thread.backtrace(this.context, Backtracer.ACCURATE)
        .map(DebugSymbol.fromAddress).join("\n\t") + "\n");
  },
  onLeave: function (log, retval, state) {
    console.log('RET :' + retval.toString());
  }

再次单击“位置”会显示更多信息

  3630 ms  -[CLLocationManager init]
  3630 ms     | -[CLLocationManager initWithEffectiveBundleIdentifier:0x0 bundle:0x0]
  3634 ms  -[CLLocationManager setDelegate:0x14c9ab000]
  3641 ms  +[CLLocationManager authorizationStatus]
RET: 0x4
  3641 ms  Called from:
0x1031aa158 TelegramUI!+[TGLocationUtils requestWhenInUserLocationAuthorizationWithLocationManager:]
    0x10337e2c0 TelegramUI!-[TGLocationPickerController initWithContext:intent:]
    0x101ee93ac TelegramUI!0x1013ac

我们看到 +[CLLocationManager authorizationStatus] 返回了 0x4 (CLAuthorizationStatus.authorizedWhenInUse) 并且被 +[TGLocationUtils requestWhenInUserLocationAuthorizationWithLocationManager:] 调用。正如我们之前预期的那样,您可以使用这种信息作为对应用程序进行逆向工程的入口点,并从那里获取输入(例如,类或方法的名称)以保持动态分析的进行。

接下来,有一种可视方式来检查使用 iPhone/iPad 时某些应用程序权限的状态,方法是打开“设置”并向下滚动,直到找到您感兴趣的应用程序。单击它时,这将打开“允许 APP_NAME 访问”屏幕。但是,并非所有权限都可能显示出来。您必须触发它们才能在该屏幕上列出它们。

例如,在前面的示例中,直到我们第一次触发权限对话框后,“位置”条目才被列出。一旦我们这样做,无论我们是否允许访问,“位置”条目都将显示出来。