hacktricks/ios-pentesting/ios-uiactivity-sharing.md

7 KiB

iOS UIActivity Sharing

UIActivity Sharing

Starting on iOS 6 it is possible for third-party apps to share data (items) via specific mechanisms like AirDrop, for example. From a user perspective, this feature is the well-known system-wide share activity sheet that appears after clicking on the "Share" button.

A full list of the available built-in sharing mechanisms can be found in UIActivity.ActivityType. If not considered appropriate for the app, the developers have the possibility to exclude some of these sharing mechanisms.

Sending Items

When testing UIActivity Sharing you should pay special attention to:

  • the data items being shared,
  • the custom activities,
  • the excluded activity types.

Data sharing via UIActivity works by creating a UIActivityViewController and passing it the desired items URLs, text, a picture on init(activityItems:applicationActivities:).

If having the source code, you should take a look at the UIActivityViewController:

  • Inspect the activities passed to the init(activityItems:applicationActivities:) method.
  • Check if it defines custom activities also being passed to the previous method.
  • Verify the excludedActivityTypes, if any.

If you only have the compiled/installed app, try searching for the previous method and property, for example:

$ rabin2 -zq Telegram\ X.app/Telegram\ X | grep -i activityItems
0x1000df034 45 44 initWithActivityItems:applicationActivities:

Receiving Items

When receiving items, you should check:

  • if the app declares custom document types ****by looking into Exported/Imported UTIs "Info" tab of the Xcode project. The list of all system declared UTIs Uniform Type Identifiers can be found in the archived Apple Developer Documentation.
  • if the app specifies any document types that it can open by looking into Document Types "Info" tab of the Xcode project. If present, they consist of name and one or more UTIs that represent the data type e.g. "public.png" for PNG files. iOS uses this to determine if the app is eligible to open a given document specifying Exported/Imported UTIs is not enough.
  • if the app properly verifies the received data by looking into the implementation of application:openURL:options: or its deprecated version [`UIApplicationDelegate application:openURL:sourceApplication:annotation:`](https://developer.apple.com/documentation/uikit/uiapplicationdelegate/1623073-application?language=objc) in the app delegate.

If not having the source code you can still take a look into the Info.plist file and search for:

  • UTExportedTypeDeclarations/UTImportedTypeDeclarations if the app declares exported/imported custom document types.
  • CFBundleDocumentTypes to see if the app specifies any document types that it can open.

A very complete explanation about the use of these keys can be found on Stackoverflow but here you have a summary:

  • UTExportedTypeDeclarations: Use them to define your own UTIs that your app wants to teach the system it is installed on. An UTI describes a piece of data _not necessarily data located inside a file!_ and requires at least an identifier `com.example.MyCoolDataType`. Additionally it may have a name `My Cool Data Type`, one or more file name extensions `.myCoolDataType`, one or more MIME types `x-application/my-cool-data-type`, one or more pasteboard types used when transferring data of that kind using copy&paste, and one or more legacy OS type. Usually you also want UTIs to conform to existing UTIs E.g. when you say your UTI conforms to `public.data`, any process that can deal with generic data can also deal with your UTI.
    • e.g.: You define your own proprietary file data format and you want this data format to be also known to other apps, plugins, extensions, and so on.
  • UTImportedTypeDeclarations: You use UTImportedTypeDeclarations do teach the system about UTIs that you want to be known in the system but that are not your UTIs.
    • e.g.: Your app is able to read the proprietary data format of another application, yet you don't know if that application is even installed on the system.
  • CFBundleDocumentTypes: You use CFBundleDocumentTypes to tell the system which Document types your app is able to open. Unless you also list your UTIs here, these UTIs are not associated with your app in Finder and your app won't appear in the Open With > menu. The only thing you always must set for a document type is the role. The role can be "Viewer" you can display that file type but you cannot edit it, "Editor" you can display and edit that file type, "None" it's not specified what you can do with that file.
    • e.g.: You want your app do be associated with certain file types, identified either by extension, by MIME type, or by UTI identifier. If you want your app to be associated with an UTI type, the app should either import or export the type, as otherwise the type may not be known to the system and registering to unknown UTI type has simply no effect at all.

Dynamic Testing

For sending activities you can:

  • Hook the method we have seen in the static analysis [`init(activityItems:applicationActivities:)`](https://developer.apple.com/documentation/uikit/uiactivityviewcontroller/1622019-init) to get the activityItems and applicationActivities.
  • Find out the excluded activities by hooking excludedActivityTypes property.

For receiving items you can:

  • Share a file with the app from another app or send it via AirDrop or e-mail. Choose the file so that it will trigger the "Open with..." dialogue that is, there is no default app that will open the file, a PDF for example.
  • Hook application:openURL:options: and any other methods that were identified in a previous static analysis.
  • Observe the app behavior.
  • In addition, you could send specific malformed files and/or use a fuzzing technique.

Read how here.