65 App Security
Dominik Schürmann edited this page 2017-02-10 09:01:40 +01:00

This page deals with security choices related to the app in relation to the Android OS. Keep in mind that these decision are not set in stone, they are temporary decisions in an ongoing design process.

Backup

  • AndroidManifest.xml has android:allowBackup="false" and android:fullBackupContent="false".
    From ./lint --show AllowBackup:

This may have security consequences for an application. adb backup allows users who have enabled USB debugging to copy application data off of the device. Once backed up, all application data can be read by the user. adb restore allows creation of application data from a source specified by the user. Following a restore, applications should not assume that the data, file permissions, and directory permissions were created by the application itself.

  • Due to android:allowBackup="false", apps such as Helium will not work
  • We explicitly do not implement a Backup Agent, so no keys are transferred to Google's cloud.
  • All keys (secret and public) are stored inside the app's sqlite database. It resides in /data/data/org.sufficientlysecure.keychain/databases/openkeychain.db
  • Like every app on Android OS, OpenKeychain is sandboxed to prevent other apps from accessing OpenKeychain's data. To emphasize this again: This means that other apps cannot access the keys of OpenKeychain under Android's security model.
  • There is only one way to get around this: If you install apps that you allow root access or apps that exploit bugs in the Android distribution on your device to do privilege escalation attacks. Even then, apps can only retrieve the secret keys containing the private values in an encrypted format. Thus, getting the private values requires reading the memory of OpenKeychain while a key is unlocked.

Why is OpenKeychain's database not encrypted?

  • Public keys are public, why encrypt them?
  • Secret keys contains private values in encrypted format, see above, encrypting them "again" on top of the encrypted private values makes no sense
  • We could use SQLCipher, but I am unsure what attack scenarios this would prevent:
    • Other apps already cannot access Openkeychain's stored data, this is enforced by Android's sandboxing
    • If a malicious app executes an exploit and gains root access, again: It can access the stored but encrypted secret keys, getting the private values requires reading the memory, this attack is not prevented by encrypting the database as they are in memory.
    • We would require another password for unlocking the SQLCipher database, so more inconvenience
    • The only argument, I can think of is protecting against root apps dumping the database and then gaining access to all public keys and thus a nice social graph, but hey, there are easier ways to get that information, maybe simply dumping the address database ;)
    • SQLCipher makes sense for apps such as TextSecure or Threema to protect the decrypted messages, but OpenKeychain does not store anything besides keys.

Anyone can delete my secret keys!

Yes.

  • Anyone can simply delete the app data from Android OS without a passphrase
  • Asking for a passphrase before delete would prevent you from deleting keys where you forgot your passphrase

Why ask for passphrase when exporting?

It is not required cryptographically, but prevents simple stealing of your keys.

So how to backup/synchronize keys?

  • Synchronize public keys with keyservers -> you achieve the same certifications on all modern OpenPGP clients
  • In OpenKeychain, go to the main key list -> Overflow menu -> "Export all keys" -> check "Also export secret keys".

Passphrase Cache

Uses Passphrase class to cache passphrases and clear them after timeout from memory

Attack scenarios

Assumption: Attacker somehow can access the device physically.

  • Cold boot attacks allow attackers to read the entire memory, including the contents of a String that has been deallocated, as long as that memory as not been allocated again.
  • Read deallocated memory using a heartbleed attack

Why Passphrase class instead of String?

  • By removing the char[] explicitly after usage the time window the passphrase is available in memory is shortened. Strings are available in memory even after deallocation. This is not true for the Passphrase class when used properly (char[] is zeroed out with removeFromMemory()).
  • Still no protection against an attacker that copies the memory while the passphrase is cached (in window of opportunity)

Attacking passphrase cache with root access

This "attack" no longer works after we introduced the Passphrase class!

A testkey has been created with the passphrase zeitgeist

  1. start Android Device Monitor
  2. 'Dump HPROF file' of org.sufficientlysecure.keychain:passphrase_cache
  3. execute:
hprof-conv org.sufficientlysecure.keychain:passphrase_cache.hprof passphrase_cache.hprof
jhat passphrase_cache.hprof
  1. open http://localhost:7000
  2. search for org.sufficientlysecure.keychain.service.PassphraseCacheService$CachedPassphrase, see PassphraseCacheService.java#L517
  3. any of the references under References to this object: will have the passphrase as instance data member

Strings are in memory, even after timeout!