iOS forensics trick: pulling databases w/o full backup

Previously on Instruments

In the previous post, I wrote about abusing some features in iOS DeveloperImage, including launching an App with custom environment variables on jailed devices.

To be honest my motivation was looking for sandbox logic issues, but failed. But at least I found this trick to abuse some feature to extract SQLite databases, which are common forensics targets, without the pain to make a fresh full backup. This scenario requires screen unlock and trusted USB connection.

To run the experiments you need to grab these tools:


The SQLite logging feature

Current built-in SQLite on iOS supports a debug option: if SQLITE_SQLLOG_DIR environment is set, every database will have a copy in the given directory, with each sql queries in plain text as well.

Our experiment starts from a jailbroken device. Just start the Gmail app with SQLITE_SQLLOG_DIR pointing to somewhere it has permission to write:

Modify the script in previous post, add a new key to the environment:

const env = ObjC.classes.NSMutableDictionary.alloc().init();
env.setObject_forKey_(
ObjC.classes.NSString.stringWithString_('/private/var/mobile/Containers/Data/Application/{THE_ACTUAL_UUID_ON_YOUR_DEVICE}/tmp'),
ObjC.classes.NSString.stringWithString_('SQLITE_SQLLOG_DIR'));

Here’s what it generates to the directory:

hello:/private/var/mobile/Containers/Data/Application/.../tmp root# ls
WebKit sqllog_05860_00000.sql sqllog_05860_00003.sql sqllog_05860_01.db
sqllog_05860.idx sqllog_05860_00001.sql sqllog_05860_00004.sql sqllog_05860_02.db
sqllog_05860_00.db sqllog_05860_00002.sql sqllog_05860_00005.sql sqllog_05860_03.db

The 05860 in file names is the pid, formatted to fixed 5 digits. The idx file is the mapping index to original databases.

root# cat sqllog_05860.idx
0 /private/var/mobile/Containers/Shared/AppGroup/21805C48-3DD1-4973-BDB8-F26441BE74B3/GIPPhenotype/phenotype.db
1 /var/mobile/Containers/Data/Application/E89CEF28-30BA-41F8-BDB3-BD05E0598D32/Library/Application Support/data/johnsmith@outlook.com/sqlitedb
2 /var/mobile/Containers/Data/Application/E89CEF28-30BA-41F8-BDB3-BD05E0598D32/Library/Application Support/data/johnsmith@outlook.com/imapsqlitedb
3 /private/var/mobile/Containers/Data/Application/E89CEF28-30BA-41F8-BDB3-BD05E0598D32/Library/Caches/com.google.Gmail/Cache.d

For example, all queries on /var/mobile/Containers/Data/Application/E89CEF28–30BA-41F8-BDB3-BD05E0598D32/Library/Application Support/data/johnsmith@outlook.com/sqlitedb are logged in sqllog_05860_00000.sql

And the sqllog_05860_00.db is the copy.


Life without jailbreak

Now the problem is, apps on iOS are imprisoned in their containers, which are still unaccessible without a full backup. Every rule has an exception, so does sandbox profile.

Some built-in apps have the privilege to write to /var/mobile/Media/iTunes_Control/iTunes

Sandbox Profiles

And some apps has com.apple.security.exception.files.absolute-path.read-write or com.apple.security.exception.files.home-relative-path.read-write entitlement.

You can read these entitlement via ideviceinstaller -l -o list_system -o xml.

VioceMemo:

<key>com.apple.security.exception.files.absolute-path.read-write</key>
<array>
<string>/private/var/mobile/Media/Recordings/</string>
</array>
<key>platform-application</key>
<true/>

MobileSafari:

<key>com.apple.security.exception.files.home-relative-path.read-write</key>
<array>
<string>/Library/com.apple.itunesstored/</string>
<string>/Library/com.apple.iTunesCloud/</string>
<string>/Library/Caches/com.apple.Music/</string>
<string>/Library/Cookies/</string>
<string>/Media/</string>
<string>/Library/Caches/com.apple.Radio/</string>
<string>/Library/Caches/com.apple.iTunesStore/</string>
<string>/Library/Caches/sharedCaches/com.apple.Radio.RadioImageCache/</string>
<string>/Library/Caches/sharedCaches/com.apple.Radio.RadioRequestURLCache/</string>
<string>/Library/com.apple.MediaSocial/</string>
<string>/Library/DeviceRegistry/</string>
<string>/Library/Logs/MediaServices/</string>
</array>

iOS allows sandboxed file access in /var/mobile/Media, exposed by AFC. Many third party iPhone management tools allows you directly manipulate this location, even with a nice GUI.

➜  afcclient git:(master) ✗ ./afcclient mkdir Downloads/SQLite

Another place that may be readable is the CrashReporter. You can grab the files with idevicecrashreport.

sandbox rules from MobileSlideShow.sb

The bad news is, not all built-in app has these exceptions, no to mention third parties.


Demo Time

During the test, launch the Instruments and use the frida script from previous post, change the bundle id to your target.

com.apple.mobilesafari

There are Safari browser state, bookmarks, history, per site preferences, HTML5 local storage and even caches. Note that typically Cache.db will not be included in backup, and it stores http requests in plain text.

➜  afcclient git:(master) ✗ ./afcclient mkdir iTunes_Control/iTunes/safari
Created directory: iTunes_Control/iTunes/safari
➜  afcclient git:(master) ✗ ./afcclient cat iTunes_Control/iTunes/safari/sqllog_02343.idx
0 /private/var/mobile/Containers/Data/Application/9210B36C-89E2-4728-9831-40CAA961C15E/Library/Image Cache/Favicons/Favicons.db
1 /var/mobile/Containers/Data/Application/9210B36C-89E2-4728-9831-40CAA961C15E/Library/Safari/BrowserState.db
2 /private/var/mobile/Containers/Data/Application/9210B36C-89E2-4728-9831-40CAA961C15E/Library/Image Cache/Touch Icons/TouchIconCacheSettings.db
3 /private/var/mobile/Containers/Data/Application/9210B36C-89E2-4728-9831-40CAA961C15E/Library/Image Cache/Password Icons/TouchIconCacheSettings.db
4 /var/mobile/Library/Safari/Bookmarks.db
5 /private/var/mobile/Containers/Data/Application/9210B36C-89E2-4728-9831-40CAA961C15E/Library/Safari/History.db
6 /var/mobile/Containers/Data/Application/9210B36C-89E2-4728-9831-40CAA961C15E/Library/WebKit/WebsiteData/LocalStorage/https_mobile.twitter.com_0.localstorage
7 /private/var/mobile/Containers/Data/Application/9210B36C-89E2-4728-9831-40CAA961C15E/Library/Safari/PerSitePreferences.db
8 /private/var/mobile/Containers/Data/Application/9210B36C-89E2-4728-9831-40CAA961C15E/Library/Caches/com.apple.mobilesafari/Cache.db

com.apple.mobilemail

➜  afcclient git:(master) ✗ ./afcclient cat Mail/sqllog_04465.idx
0 /var/mobile/Library/Mail/Envelope Index
1 /var/mobile/Library/Mail/Protected Index
2 /var/mobile/Library/DeviceRegistry/5CFB9E7E-C465-4A92-B3ED-C744367AB766/NanoMail/registry.sqlite
3 /var/mobile/Library/AddressBook/AddressBook.sqlitedb

com.apple.mobilephone

Address Book and call history:

hello:~ root# procexp all fds | grep -i sms.db
IMDPersistenceA 812 FD 4u /private/var/mobile/Library/SMS/sms.db @0x0
IMDPersistenceA 812 FD 5u /private/var/mobile/Library/SMS/sms.db-wal @0x0
IMDPersistenceA 812 FD 6u /private/var/mobile/Library/SMS/sms.db-shm @0x0
hello:~ root# ps aux | grep 812
mobile 812 0.0 0.0 1664672 1296 ?? Ss 22Oct18 0:01.77 /System/Library/PrivateFrameworks/IMDPersistence.framework/XPCServices/IMDPersistenceAgent.xpc/IMDPersistenceAgent
root 6008 0.0 0.1 1593504 1536 s000 S+ 2:50PM 0:00.01 grep 812
hello:~ root#
➜  afcclient git:(master) ✗ ./afcclient mkdir iTunes_Control/iTunes/Phone
Created directory: iTunes_Control/iTunes/Phone
➜  afcclient git:(master) ✗./afcclient cat iTunes_Control/iTunes/Phone/sqllog_04322.idx
0 /var/mobile///Library/CallHistoryDB/CallHistory.storedata
1 /var/mobile///Library/CallHistoryDB/CallHistoryTemp.storedata
2 /var/mobile/Library/AddressBook/AddressBook.sqlitedb

But you will not be able to pull sms.db, because it’s owned by xpc service IMDPersistenceAgent. The message appcom.apple.MobileSMS communicates with it via XPC instead of opening the database.