(lldb) thread step-out

Alpina.Books: iOS App Forensics for eBooks Smuggling

Disclaimer: results of this research were sent to app developers back in February 2020. Since then a major release was rolled out, so I assume developers had fixed everything they had wanted to.

I read a lot, and love non-fiction. But when it comets to ebooks, I prefer native Books.app of iOS - I got used to its controls, animations, and feeling of a “one-stop shop” for all the books I've read lately. So, every time I happen to buy a ebook, first thing I look for is - how can this book be imported into Books.app?

Same was the case with a books of a prominent Russian publisher Alpina Digital back in February. I've bough a book in their Alpina.Books iOS app (version 6.6.14 at that time) and only then noticed that there's no Export button. Is that a problem for reverse engineer? Nope!

First thing first, all iOS apps have 3 locations in the file system where their stuff can be stored:

  1. application bundle - executable and resources installed from AppStore
  2. user data sandbox - everything that the app generates during it lifetime - saved files, local databases, UserDefaults plist, pre-backgrounding screenshot, etc
  3. shared App Groups - same as sandbox, but shared among one or more applications of one developer

On my jailbroken test device, I've found where the user data sandbox is located (somewhere under /var/mobile/Containers/Data/Application/) and transferred it to my mac via SSH using scp command. What do we have there?

Local Database

Cool, let's try to open this Realm database with an official RealmBrowser. A lot of tables:

Let's peek at DBUser - it's pretty simple and had only 2 rows in my case, and one of them has a string with email address I've used during registration. It also has a reference to some DBItem in a column inventoryArray, and that table looks more interesting:

Following looks curious:

  1. title - same as the book I've bought
  2. book - reference to DBBook table
  3. dbFiles - reference to DBFiles table
Let's check the last one:
And here we go, just copy the downloadLink into our browser and full unprotected ebook is downloaded.

Mitigation

  1. Network calls should be authneticated! There is no reason to allow non-authenticated callers to download any user-related content - this can be a server-side vulnerability called URL enumeration;
  2. Realm database has an encryption mechanism built-in. Enabling it, all developers will need to care about is key management.


File System Artefacts

Another interesting thing in working directory is files folder with some strangely named contents (and similar to something we've already seen in DBBook table):

Inside the 33294 folder we can see subfolders: Text with a bunch of html files, Images with illustrations we've previously seen in the book, and file named mimetype. Lets check out what's in that tiny file:abjurato@Macintosh ~ % cat mimetypesays this file is just a epub archive:application/epub+zip%

Here we go, just rename 33294.zip to 33294.epub and we've got the book:

What is more curious, this folder is not excluded from the backup and is not protected with data protection keys - which means attacker does not even need a jailbroken device because all downloaded books will be included into a device backup that is stored on their computer and can be inspected using iExplorer utility.

Mitigation

  1. first, all the sensitive info that may be transferred from server should be excluded from backups. Backups can be stolen, they can be inspected, etc. Settings data protection key will also protect data at rest:

    On a jailbroken device, verification of data protection keys can be performed using FileDp tool by @satishb3.

  2. Then, the hard part is protection of data on a compromised device - in the extreme case it may be encrypted with a key that is never stored on device and it input by a user at runtime, similar to AppKey architecture we've implemented at ProtonMail. For a ebooks library tho (as we'll see in an upcoming article about Amazon Kindle app), custom book file format can work really well.


Bonus: AppStore Receipt

As we can see from AppStore page of the app, all books are available via one-time In-App Purchase. This is the reason we see a folder called StoreKit in the user data directory - iOS creates this folder on behalf of the app and saved a receipt file there with info about all purchases and subscription made by user in this app.

Receipt file has a pretty complex structure, and while technically it is possible to read, decypher and validate it programmatically, there is easier way to get to its contents - by sending it to Apple servers which will respond with a JSON:

abjurato@Macintosh ~ % curl -d '{"receipt-data":BASE64_STRING_FROM_RECEIPT}' -X POST https://buy.itunes.apple.com/verifyReceipt


Sources

[1] Mobile Security Testing Guide - Data storage on iOS

[2] ProtonMail AppKey local storage protection

[3] AppStore Receipt Validation


Tools

[4] Realm encryption APIs

[5] iExplorer

[6] FileDp


04/10/2020