iOS – Tracking Bundle IDs for Containers, Shared Containers, and Plugins
In iOS, one of the more vexing things I’ve found when working through data or helping a student with questions usually comes back to tracking what application is responsible for putting data in a specific place. With some of the fantastic work done by others including Alexis Brignoni on the ApplicationState.db as part of the FrontBoard directory, it has always become one of my first go-to spots to build a “treasure map” of applications to deal with those annoying AppGUIDs that Apple assigns each app on a device. These annoying things I speak of can be found when you’re looking for data in:
/private/var/mobile/Containers/Data/Application
Luckily, most tools will parse out the ApplicationState.db and map each one of these unique IDs to the application which is stored within.
Great! So much easier to go and figure out what apps are living where. However sometimes you stumble upon a file of interest within a folder and you’re left with the task of matching the directory path to this database. Maybe you’re in a situation where you’re working with just the raw image and limited access to tools as well. How can we find the app’s bundleID from within a directory already?
Within the application data path, at the root there should be a file “.com.apple.mobile_container_manager.metadata.plist” which seems to be same name in each application directory. This information will contain keys that contain the bundleID of the application which is great if you’re in a pinch and don’t want to jump back and forth.
The more interesting thing is what happens when you do a search for this file across your iOS device. If you do, you’ll see that the .com.apple.mobile_container_manager.metadata.plist file appears in a lot of places including:
- /private/var/containers/Bundle/Application/APPGUID/
- /private/var/containers/Shared/SystemGroup/APPGUID/
- /private/var/containers/Data/System/APPGUID/
- /private/var/mobile/Containers/Shared/AppGroup/APPGUID/
- /private/var/mobile/Containers/Data/Application/APPGUID [duh]
- /private/var/mobile/Containers/Data/InternalDaemon/APPGUID/
- /private/var/mobile/Containers/Data/PluginKitPlugin/APPGUID/
Whoa. That’s a lot more places for us to explore to make our treasure map. So what is this file anyway? First, let’s talk about Sandboxing. Apple heavily utilities sandboxing in iOS. This is to prevent applications from getting access to data they’re not supposed to have access to. Each application is given its own sandbox to play in and only that area to play in. This plist file allows us to see what sandbox we’re in and who owns that sandbox from an application perspective. Using this information, we can break down a little bit more of this path information above to figure out why certain apps may be keeping data in a location.
/private/var/containers/Bundle/Application/
This directory is where the .app lives on the device. There’s some additional data we can track here about the application itself and who downloaded it onto the device. Along with the .app, there’s an iTunesMetadata and BundleMetadata plist file that can list out information such as when the application was downloaded, what version of the app was downloaded, and what AppleID actually downloaded it.
/private/var/containers/Shared/SystemGroup/
This directory is similar to the one above, but speaks to core applications of the iOS device. There’s less information in here but still a .plist file that can reveal what system application is responsible for the container. /
private/var/containers/Data/System/
Again, similar to the directory above, but these seemed to be system apps that didn’t want to share information between core applications. Again, less relevant information except for the bundleID who owns the container.
/private/var/mobile/Containers/Shared/AppGroup/
Now this is where the REAL fun begins! I mentioned sandboxing earlier. Apple says that applications are not allowed to share information without requesting it through official channels first. In order to share information, application developers can assign a “group” to their application. According to Apple’s developer information, these groups can then share data between each other. You may have also seen these in backup-style images that are listed as “AppDomainGroup-group.bundleID” instead of the “AppDomain-com.bundle.ID” structure. I have often used this path when I couldn’t find the data I was looking for in the main Application Data path.
Now for the downside. The ApplicationState.db doesn’t contain information about this path. The upside? Each application’s “Shared/AppGroup” directory will have one of our .com.apple.mobile_container_manager.metadata.plist files! Woohoo! To make it even better, Alexis Brignoni has built support into iLeapp in order to list out out all of these files from this directory allowing us to match the contents of the file to the path it lives in. [Get iLeapp here]
An application may also have more than one folder in this path. A couple of examples would be the Dropbox application that over 4 different containers here and the Spark email app which had 2. More importantly, some applications may keep all of their relevant data here instead of the /private/var/mobile/Containers/Application/Data/ directory. An example of this would be the Spark email application (iTunes web link) which chooses to store all of its relevant databases within the /private/var/mobile/Containers/Shared/AppGroup/ directory structure instead of the more common /private/var/mobile/Containers/Application/Data/ directory structure. [Other notable examples of this include WhatsApp and Signal]
/private/var/mobile/Containers/Application/Data
The place where we’re supposed to look for app data. Well understood and documented. Just, not where we always end up wanting to look after all.
/private/var/mobile/Containers/Application/InternalDaemon
In my test devices these appeared to be Apple services (or internal daemons, obviously) that could be tracked using the same .com.apple.mobile_container_manager_metadata.plist files.
/private/var/mobile/Containers/Application/PluginKitPlugin/
I’ve had two situations recently that I’ve been assisting students with to understand where crucial data to their cases has wound up within this area. Populating exact matching data here is difficult but a few situations arose in which I was able to track a good bit of information. Because Apple is allowing applications to use plugins to tie together (think of the Giphy keyboard, my personal favorite), these plugins can keep data within this directory structure. One test case was to figure out why a bunch of illicit videos were showing up within a specific directory. By using the .com.apple.mobile_container_manager.metadata.plist file, the analyst was able to figure out what plugin was helping to put data in this directory and what bundleID the plugin belonged to. In this case, it was tied to com.apple.mobileslideshow’s PhotoMessagesApp.
Note: com.apple.mobileslideshow is the Photos application on iOS.
Now that we know what plugin and what application the directory belongs to, we can then go out and try to generate data to prove how this information gets in here. In my example, I used the photo picker plugin within iMessage and then modified the video directly within that plugin without launching the original com.apple.mobileslideshow application. Using KnowledgeC, you can see in the following screenshots that when these files were created within the PluginKitPlugin/APPGUID/ directory structure that the MobileSMS application and other plugins overlap.
Other plugins such as ‘com.apple.mobileslideshow.photo-picker’ have come up in other investigations but sometimes it’s difficult to populate these directories without KnowledgeC or PowerLog to go on. By at least understanding the owning BundleID, we can start to understand possibilities for how data got where it is.
Now we have a better way to build out our own treasure maps as well as now knowing that .com.apple.mobile_container_manager.metadata.plist files are typically going to provide the “X” that marks the spot.
This post was authored by Christopher Vance, Manager, Curriculum Development at Magnet Forensics. It also appears on his D20 Forensics Blog.