Skip to content

Port MASTG-TEST-0069: Testing App Permissions (ios) (by @appknox)#3673

Open
sk3l10x1ng wants to merge 5 commits intoOWASP:masterfrom
sk3l10x1ng:port_mastg_test_0069
Open

Port MASTG-TEST-0069: Testing App Permissions (ios) (by @appknox)#3673
sk3l10x1ng wants to merge 5 commits intoOWASP:masterfrom
sk3l10x1ng:port_mastg_test_0069

Conversation

@sk3l10x1ng
Copy link
Collaborator

closes #2969

@cpholguera cpholguera changed the title Port MASTG-TEST-0034: Testing App Permissions (ios) (by @appknox) Port MASTG-TEST-0069: Testing App Permissions (ios) (by @appknox) Jan 30, 2026

If an app declares entitlements that are not justified by its core functionality, it gains access to privileged capabilities beyond standard sandbox restrictions — such as HomeKit, HealthKit, VPN configuration, or iCloud containers. This can lead to unauthorized access to sensitive user data, expanded attack surface, or privacy violations through excessive privilege.

On iOS, entitlements are declared in the provisioning profile (`embedded.mobileprovision`) as a cryptographically signed property list. They represent permissions granted by Apple's provisioning system for capabilities that go beyond the default app sandbox.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

embedded.mobileprovision is available only on apps built for: Development, Ad Hoc distribution, Enterprise distribution. We might need to mention it, so the testers won't have issues when searching for them?

func requestAllPermissionsSequentially(completion: @escaping (String) -> Void) {
self.completionHandler = completion
resetState()
requestLocationPermission()
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just for clarity:

Suggested change
requestLocationPermission()
requestLocationPermission()
// Subsequent requests are triggered within delegates or callbacks


private func requestLocationPermission() {
locationManager.requestWhenInUseAuthorization()
locationManager.requestAlwaysAuthorization()
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shouldn't we call requestAlwaysAuthorization() after the request for requestWhenInUseAuthorization() finishes?

In other words, why don't we call requestAlwaysAuthorization() from func locationManager(.., didChangeAuthorization status: CLAuthorizationStatus)

completionHandler?(results)
}

func locationManager(_ manager: CLLocationManager, didChangeAuthorization status: CLAuthorizationStatus) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if granted {
manager.startUpdatingLocation()
}
requestCameraPermission()
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shouldn't we call it on the main thread similarly to the other cases?

Suggested change
requestCameraPermission()
DispatchQueue.main.async {
requestCameraPermission()
}

Or even wrap a bigger part of code?


## Overview

If an app embeds entitlements in its binary that are not justified by its core functionality, it gains access to privileged capabilities such as HomeKit, HealthKit, VPN configuration, or shared app groups. This can lead to unauthorized access to sensitive user data, an expanded attack surface, or privacy violations through excessive privilege.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we have a Knowledge page about embedded entitlements and external one. Just to clarify why there are both places. We could also describe there that an app needs to have a usage description in Info.plist

Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR ports the legacy iOS test MASTG-TEST-0069 (Testing App Permissions) to the v2 structure by deprecating the v1 test and adding new v2 test(s), an iOS technique page, and multiple iOS demos intended to demonstrate permission declarations and runtime permission usage.

Changes:

  • Deprecates the v1 test tests/ios/MASVS-PLATFORM/MASTG-TEST-0069.md and links it to new v2 coverage.
  • Adds four new v2 iOS test pages related to purpose strings and entitlements under tests-beta/ios/.
  • Adds a new iOS technique page and several new iOS demos (static and dynamic) with scripts and captured outputs.

Reviewed changes

Copilot reviewed 20 out of 23 changed files in this pull request and generated 30 comments.

Show a summary per file
File Description
tests/ios/MASVS-PLATFORM/MASTG-TEST-0069.md Marks the v1 test as deprecated and attempts to point to v2 replacements via covered_by.
tests-beta/ios/MASVS-PRIVACY/MASTG-TEST-0x69.md Adds a new v2 static test for excessive Info.plist purpose strings.
tests-beta/ios/MASVS-PRIVACY/MASTG-TEST-0x69-1.md Adds a new v2 static test for entitlements in embedded.mobileprovision.
tests-beta/ios/MASVS-PRIVACY/MASTG-TEST-0x69-2.md Adds a new v2 static test for entitlements embedded in the app binary.
tests-beta/ios/MASVS-PRIVACY/MASTG-TEST-0x69-3.md Adds a new v2 dynamic test for runtime tracing of permission API calls.
techniques/ios/MASTG-TECH-0x69.md Adds a technique page intended to explain how to obtain and review iOS permissions/capabilities.
demos/ios/MASVS-PRIVACY/MASTG-DEMO-0x69/MASTG-DEMO-0x69.md Adds a demo documenting purpose strings in Info.plist.
demos/ios/MASVS-PRIVACY/MASTG-DEMO-0x69/MastgTest.swift Adds a Swift sample that requests many permissions sequentially for demo purposes.
demos/ios/MASVS-PRIVACY/MASTG-DEMO-0x69/Info.plist Adds a demo Info.plist artifact used by the purpose-string demo.
demos/ios/MASVS-PRIVACY/MASTG-DEMO-0x69/run.sh Adds an automation script to extract/grep purpose-string keys from Info.plist.
demos/ios/MASVS-PRIVACY/MASTG-DEMO-0x69/output.txt Adds captured output listing UsageDescription keys found in the plist.
demos/ios/MASVS-PRIVACY/MASTG-DEMO-0x69/embedded.mobileprovision Adds a provisioning profile artifact used by entitlement demos.
demos/ios/MASVS-PRIVACY/MASTG-DEMO-0x69-1/MASTG-DEMO-0x69-1.md Adds a demo documenting entitlements in embedded.mobileprovision.
demos/ios/MASVS-PRIVACY/MASTG-DEMO-0x69-1/run.sh Adds an automation script to decode the provisioning profile with security cms.
demos/ios/MASVS-PRIVACY/MASTG-DEMO-0x69-1/output.txt Adds captured decoded provisioning-profile output.
demos/ios/MASVS-PRIVACY/MASTG-DEMO-0x69-2/MASTG-DEMO-0x69-2.md Adds a demo documenting entitlements extracted from the signed binary.
demos/ios/MASVS-PRIVACY/MASTG-DEMO-0x69-2/run.sh Adds an automation script using rabin2 to extract entitlements.
demos/ios/MASVS-PRIVACY/MASTG-DEMO-0x69-2/output.txt Adds captured entitlements output.
demos/ios/MASVS-PRIVACY/MASTG-DEMO-0x69-3/MASTG-DEMO-0x69-3.md Adds a demo documenting runtime tracing of permission APIs with Frida.
demos/ios/MASVS-PRIVACY/MASTG-DEMO-0x69-3/run.sh Adds a Frida spawn script for the runtime tracing demo.
demos/ios/MASVS-PRIVACY/MASTG-DEMO-0x69-3/output.txt Adds captured Frida output showing permission API calls.
demos/ios/MASVS-PRIVACY/MASTG-DEMO-0x69-3/script.js Adds a Frida script intended to hook many iOS permission-related APIs.

id: MASTG-TEST-0x69
type: [static]
weakness: MASWE-0117
profiles: [L1, L2]
Copy link

Copilot AI Feb 10, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For MASVS-PRIVACY tests, profiles is typically [P] (e.g., tests-beta/ios/MASVS-PRIVACY/MASTG-TEST-0281.md:7 and tests-beta/android/MASVS-PRIVACY/MASTG-TEST-0254.md:7). Using [L1, L2] here looks inconsistent; please switch to [P] (or justify why this permission-privacy test belongs to L1/L2).

Copilot uses AI. Check for mistakes.
Comment on lines +24 to +28
## Observation

The output lists 16 purpose strings found in the `Info.plist` file, indicating the app declares access to a wide range of protected resources.

{{ output.txt }}
Copy link

Copilot AI Feb 10, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The demo claims it finds “purpose strings” and the test expects key/value pairs, but run.sh only greps for UsageDescription and the committed output.txt contains only <key>...UsageDescription</key> entries (no <string>...). Update the script/output to include the associated description values, or adjust the text to accurately state that only keys are collected.

Copilot uses AI. Check for mistakes.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

True, it's not just about the keys being there. They also MUST have an actual appropriate description that serves as rationale about the need for that permission.

@@ -0,0 +1 @@
security cms -D -i ../MASTG-DEMO-0x69/embedded.mobileprovision > output.txt No newline at end of file
Copy link

Copilot AI Feb 10, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

run.sh is missing a shebang (other demos use #!/bin/bash) and basic safety flags. Add a shebang and set -euo pipefail so the demo fails fast and can be executed consistently by automation.

Copilot uses AI. Check for mistakes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

MASTG v1->v2 MASTG-TEST-0069: Testing App Permissions (ios)

3 participants