In the first part of the article, we have discussed about the iPhone application traffic analysis. Second part of the article covered the privacy issues and property list data storage. Third part covered in-depth analysis of the iOS keychain data storage. In this part we will take a look at different types of files stored/created in the application’s home directory and other insecure data storage locations.
Sqlite is a cross-platform C library that implements a self-contained, embeddable, zero-configuration SQL database engine. Sqlite database does not need a separate server process and the complete database with multiple tables, triggers, and views is contained in a single disk file. The Sqlite database offers all the standard SQL constructs, including Select, Insert, Update and Delete. As Sqlite is portable, reliable and small, it is an excellent solution for persistent data storage on iOS devices.
Sqlite library that comes with iOS is a lightweight and powerful relational database engine that can be easily embedded into an application. The library provides fast access to the database records. As the complete database is operated as a single flat file, applications can create local database files and manage the tables & records very easily. In general, iOS applications use the Sqlite database to store large and complex data as it offers good memory usage and speed. Sqlite database that comes with iOS does not have a builtin support for encryption. So most of the iOS applications store lots of sensitive data in plain text format in Sqlite files. For example, to provide offline email access, Gmail iOS application stores all the emails in a Sqlite database file in plain text format.
Unencrypted sensitive information stored in a Sqlite file can be stolen easily upon gaining physical access to the device or from the device backup. Also, if an entry is deleted, Sqlite tags the record as deleted but not purge them. So in case if an application temporarily stores and removes the sensitive data from a Sqlite file, deleted data can be recovered easily by reading the Sqlite Write Ahead Log.
The Sqlite files can be created with or without any file extention. Most common extentions are .sqlitedb &.db. The below article explains, how to view Sqlite files and how to recover the deleted data from Sqlite files on the iPhone. For this exercise, I have created a demo application called CardInfoDemo. CardInfoDemo is a self signed application, so it can only be installed on a Jailbroken iPhone. The CardInfo demo application accepts any username & password, then collects the credit card details from the user and stores it in a Sqlite database. Database entries are deleted upon logout from the app.
Steps to install the CardInfo application:
1. Jailbreak the iPhone.
2. Download the CardInfoDemo,ipa file - Download link.
3. On Windows, download the iPhone configuration utility – Download link.
4. Open the iPhone configuration utility and drag the CardInfoDemo.ipa file on to it.
5. Connect the iPhone to the windows machine using USB cable. Notice that the connected device is listed in the iPhone configuration utility. Select the device and navigate to Applications tab. It lists the already installed applications on the iPhone along with our CardInfo demo app.
6. Click on Install button corresponding to the CardInfo application and it installs the CardInfo application on to the iPhone.
Steps to view CardInfo Sqlite files:
1. On the Jailbroken iPhone, install OpenSSH and Sqlite3 from Cydia.
2. On windows workstation, download Putty.
3. Connect the iPhone and the workstation to the same Wi-Fi network. Note: Wi-Fi is required to connect the iPhone over SSH. If the Wi-Fi connection is not available SSH into the iPhone over USB.
4. Run Putty and SSH into the iPhone by typing the iPhone IP address, root as username and alpine as password.
5. Navigate to /var/mobile/Applications/ folder and identify the CardInfo application directory using ‘find . –name CardInfo’ command. On my iPhone CardInfo application is installed on the – /var/mobile/Application/B02A125C-B97E-4207-911B-C136B1A08687/ directory.
6. Navigate to the /var/mobile/Application/B02A125C-B97E-4207-911B-C136B1A08687/CardInfo.app directory and notice CARDDATABASE.sqlite3 database file.
7. Using sqlite3 command, view the CARDDATABASE.sqlite3 and notice that CARDINFO table is empty.
Note: Sqlite files can also be copied from the iPhone to a workstation over SSH and viewed using Sqlite data browser & Sqlite spy tools.
8. On the iPhone, open CardInfo application and login (works for any username and password).
9.Enter credit card details and click on Save button. In the background, it saves the card details in the Sqlite database.
10. View CARDDATABASE.sqlite3 and notice that CARDINFO table contains the credit card details data.
11. Logout from the application on the iPhone. In the background, it deletes the data from the Sqlite database.
12. Now view CARDDATABASE.sqlite3 and notice that CARDINFO table is empty.
Steps to recover the deleted data from CardInfo Sqlite file:
Sqlite database engine writes the data into Write Ahead Log before storing it in the actual database file, to recover from system failures. Upon every checkpoint or commit, the data in the WAL is written into the database file. So if an entry is deleted from the Sqlite database and there is no immediate commit query, we can easily recover the deleted data by reading the WAL. In case of iOS, strings command can be used to print the deleted data from a Sqlite file. In our case, running ‘strings CARDDATABASE.sqlite3’ command prints the deleted card details.
In iOS, if an application uses the Sqlite database for temporary storage, there is always a possibility to recover the deleted temporary data from the database file.
For better security, use custom encryption while storing the sensitive data in Sqlite database. Also, before deleting a Sqlite record, overwrite that entry with junk data. So even if someone tries to recover the deleted data from the Sqlite file, they will not get the actual data. Use iOS data protection constants while creating the Sqlite files.
Most of the iOS applications do not want to prompt the user for login everytime. So they create persistent cookies and store them in cookies.binarycookies file on the application’s home directory. During penetration test, investigate the cookies.binarycookies file for sensitive information and to find session mangement issues. Cookies.binarycookies is a binary file and the content is not in readable format. So I wrote a python script BinaryCookieReader.py that can read the cookie file and display the content on the screen.
Steps to read the Cookies.binarycookies:
1. On Windows, download WinScp, Python & BinaryCookieReader.py.
2. Connect the iPhone and the workstation to the same Wi-Fi network.
3. Run WinScp and SSH into the iPhone by typing the iPhone IP address, root as username and alpine as password.
4. Navigate to the Library/Cookies folder in the application’s home directory.
5. Copy the Cookies.binarycookies file to the windows machine by dragging it.
6. On windows, open command prompt and run the below command to list the contents of cookies.binarycookies file.
Python BinaryCookieReader.py [Cookies.binarycookies file path]
Below is the screenshot of cookies created by Facebook iOS Application.
In an effort to learn how user’s type, iOS devices utilize a feature called Auto Correction to populate a local keyboard cache on the device. The keyboard cache is designed to autocomplete the predictive common words. The problem with this feature is, it records everything that a user types in text fields. The cache keeps a list of approximately 600 words. The keyboard cache is located at Library/Keyboard/en_GB-dynamic-text.dat file. To view the Keyboard cache, copy the en_GB-dynamic-text.dat file to a computer over SSH and open the file using a Hex Editor. Below is the screenshot of a keyboard cache Hex view.
Keyboard Cache does not store the informtion typed in the fields which are marked as Secure. By default, passwords and strings with all digits (pins & credit cards) are marked as Secure. Hence the data typed in those fields does not store in the keyboard cache. But data typed in other text fields like username, security questions & answers might get stored in the keyboard cache. During a pentest clear the existing keyboard cache by navigating to iPhone Settings -> General -> Reset -> Reset Keyboard Dictionary (shown in the below image), then browse the application & enter data in text fields and anlyze whether the data is getting stored in the keyboard cache or not.
During the application development, to disable auto complete for a text field, either mark it as secure (ex: mytextField.secureTextEntry = YES) or disable the autocomplete (mytextField.autocorrectionType = UITextAutocorrectionTypeNo;).
Along with the keyboard cache, when a user copies data from a textfield, iOS stores the data into a pasteboard (clipboard in other operating systems). The pasteboard is shared among all the application, so the information copied in one application can be accessed from other application by reading the pasteboard. If the application is dealing with senstive data, it is recommended to use private or application specific pasteboard.
Pressing the iPhone home button shrinks the iOS application and moves it to the background with a nice effect. To create that shrinking effect, iOS takes a screenshot of the application and stores it in the Library/Caches/Snapshots folder in the respective application’s home directory. This might result in storing the user’s sensitive information on the device without user’s knowledge. Snapshots stored on the iPhone will automatically cleared after the device is rebooted.
Ex: Incase of Gmail iOS application, when a user press the iPhone home button after viewing the email, a snapshot of users’ email gets stored on the device without user’s knowledge. Below snapshot is captured after viewing a mail from the Citibank.
During development, the application snapshot problem can be fixed in two ways.
1. Remove sensitive data or change the screen to blank before the applicationDidEnterBackground()
2. Instead of hiding or removing sensitive data, application’s back grounding can be disabled altogether by setting the “Application does not run in background” property in the application’s Info.plist file.
Along with plist files, sqlite files, binary cookies & snapshots, iOS applications can store other format files like pdf, xls, txt, etc. when viewed from the application. For example, in Yandex.Mail iPhone application, when a user views an attachment it gets stored on the device and remains on the device even after user logged out from the mail application. Applications which are storing temp files on the device, should clear those files upon logout/close for better security. Below is the screenshot of Yandex.Mail attachement directory.
In general, iOS applications write data into logs for diagnostic and troubleshooting purpose. Also, during development, applictions developers commonly use NSLog for debugging purpose. These logs might include requests, responses, cookies, authentication tokens and other sensitive data. On the iPhone, data passed to the NSLog funciton is logged by Apple System Log (ASL) and the data remains on the log until the device is rebooted. Also, Error logs are not bounded by the application sandbox. Which means, error log generated by one application can read by other application. So if an application logs sensitive data, a malicious application can actively query for this data and send it to a remote server.
Error logs on the iPhone can be viewed directly using Console app. Console app is available in AppStore. Error logs can also be viewed using iPhone configuration utility or by syncing the device with iTunes and looking at CrashReporter folder.
For this exercise, I have created a demo application called CardInfoDemo. CardInfoDemo is a self signed application, so it can only be installed on a Jailbroken iPhone. The CardInfo demo application accepts any username & password, then collects the credit card details from the user and writes it into the error log.
Steps to view the error logs:
1. Install CardInfoDemo application on the iPhone.
2. On windows, install & open the iPhone Configuration Utility.
3. Connect the iPhone to the windows machine using USB cable. Notice that the connected device is listed in the iPhone configuration utility. Select the device and navigate to Console tab.
4. On the iPhone, open CardInfo application and login (works for any username and password).
5. Enter credit card details and click on Save button. In the background, it logs the card details.
6. On the iPhone configuration utility console tab, you can notice the card details logged by the CardInfoDemo application.
For better security, do not log sensitive data. Also, remove debugging and troubleshooting logs from the application before publishing it.
Penetration Testing For iPhone Applications is going to be covered in a series of articles. In the Part 5, we will take a look at runtime analysis of iOS Applications.
1. Debunking NSLog Misconceptions
2. What’s in your iOS Image Cache ?
3. Hacking and Securing iOS Applications by Jonathan Zdziarski