Sonntag, 7. Dezember 2014

Why passwords should not be stored on a mobile device



Apps for mobile devices, like tablets and smartphones replace more and more the traditional desktops and notebooks for internet-based services. For a solid number of apps in the various App Stores it is nearly every time mandatory for the users to authenticate against the App (for using the services the App provides). This often raises the question how to store the username and the password on the device securely. The easy answer to this is: unfortunately not possible. A Keychain to store sensitive data securely has been offered by iOS since version 2.0 and by Android since version 4.0, but you should keep in mind that it is still possible to read all those values stored there.


The problem:

Since the Keychain on Android was established in version 4.0 and apps often have to support older versions, the only possibility is to use the integrated AccountManager or the Shared Preferences folder, which every app has included. On iOS you can use the Keychain without hesitation. It is also possible to save informations within the app folder structure (preferences files or SQLite database).

The Keychain on both systems has a prevention against unauthorized access, but both systems are Linux/Unix-based and they share a user who has access to everything: root. By using a root exploit it is possible to read all stored secrets on a mobile device. Since Android is suffering from a complicated update policy it is much easier to achieve this: regarding the current statistics [1] still 9.6% of Android devices are using the old versions Froyo and Gingerbead (2.2 - 2.3.7). 33.9% are using KitKat (4.4) and the newest version Lollipop (5.0) isn't even mentioned. Especially the devices with Gingerbead and Froyo won't get any new updates to fix security vulnerabilities. On iOS it is often argued that there are no root expoits, but the Jailbreak community has found one for every single version and has published it. Currently team TaiG has found one for the newest iOS version 8.1.1. For iOS 8.0 team Pangu published it and for iOS 7 it was the Evasi0n team. A root exploit for iOS is sold on the black market for 500.000$ to 1.000.000$ [2]. Public authorities like the NSA are willing to pay such an amount. Nevertheless, this does not necessarily mean that there are no exploits if they aren't publicly available.


Let's have a quick look at the Keychains:


The Keychain file itself (keychain-2.db) is protected with the device key, which can be obtained through jailbreaking / root exploit. Every entry is encrypted with the passcode key. When unlocked the users passcode is encrypted many times using a modified PBKDF2 (Password-Based Key Derivation Function 2) algortihm (AES with the UID key) to generate the passcode key. This key is hold in memory till the device is locked. A lot of users are using just a 4 digits pin which makes it easy to brute-force (average time is about 15 minutes). Hopefully this get's better with the new Touch ID feature, introduced with the iPhone 5S.




Each Keychain Entry is encrypted with the 128-bit AES master key in CBC mode. The master key is a 128-bit key created by reading from /dev/urandom. It is encrypted with a hash of the users lockscreen password created with the PBKDF2 function from the SSL library (till Android version 4.3.x). Since Android 4.4 (KitKat) the PBKDF2 key derivation function (KDF) is replaced with scrypt [3].


The solution:

The question for an app developer now is: How can you make sure that the customers can use the app with all features without storing the password on the device? The solution: a token-based approach like OAuth 2.0 [4]. During the first start-up of my app, the customer has to provide his username and  password once. Afterwards, the app receives a token from the server which is going to be used as authentication. This token can be stored encrypted in the Keychain. The advantage of this  approach is that if an invader gets access to the device or records the token via a Man-in- the-Middle attack, he only receives a restrictive token which is only usable for certain use-cases (like viewing only some content, synchronising contacts and so on). He won't receive the password for an email account or maybe a bank account and so on. Tokens also have the advantage that they can be  revoked and only are valid for a certain time.


tl;dr
Currently there is no practical way to store a password safely on a mobile device. Only the token-based approach is helpful here.


Links:
[1] http://developer.android.com/about/dashboards/index.html
[2] http://grahamcluley.com/2013/07/zero-day-ios-exploit/
[3] https://www.tarsnap.com/scrypt.html
[4] http://oauth.net/2/

Donnerstag, 23. Oktober 2014

Why Samsung Knox isn't really a Fort Knox ***UPDATE***

UPDATE #2:

Apparently Samsung said in their press release that user should try out My Knox, as Knox Personal is deprecated. I just tried to install it but sadly My Knox only works on Samsung Galaxy S5 and Samsung Galaxy Note4. So Samsung, you're leaving all devices older than the S5 with a vulnerable version of Samsung Knox??

UPDATE:

As Samsung responded with an official press release regarding my blog article (https://www.samsungknox.com/en/blog/response-blog-post-samsung-knox) I also want to response to their press release:

  • First of all as I mentioned in the paragraph below, I analysed the pre-installed Knox Container App which is known as Knox Personal and shipped with the Samsung S4 I bought and not Knox EMM. " Knox EMM is a enterprise cloud-based management solution for mobile devices which was not part of this analysis."
  • I investigated the following version (mentioned in the name of the apk files on the device): KNOX_com.sec.knox.app.container_2.0_2.apk, KNOX_com.sec.knox.containeragent_3.0_30.apk
  • A lot of comments and posts claimed that I have just investigated an early developer version. I don't think that version 2.0_2 seems to be an early developer version?!? Also Samsung why are you shipping early developer versions of a product on customer devices? 
  • I did the analysis about one month ago with a new Samsung S4 and all updates installed. That doesn't seem to be an early developer version, right? Or did I bought a fake one ;)?
  • Samsung mentioned the following in their press release: "Concerning the second issue, KNOX does save the encryption key required to auto-mount the container’s file system in TrustZone. However, unlike what is implied in the blog, the access to this key is strongly controlled. Only trusted system processes can retrieve it, and KNOX Trusted Boot will lock down the container key store in the event of a system compromise."
  • I think Samsung speaks here about their Knox Agent. At the beginning of my analysis I used geohots towelroot to gain root access on the Samsung device. During the analysis the phone wanted to update some "Samsung Security Policies". After the update the Agent blocked the root access to the phone. So this agent seems to be working like a usual Anti-Virus tool. It can only detect attacks if it knows the attack. And as we all know, Anti-Viruses are useless against unknown attacks :). This is the same for their so called "TrustZone".
  • All other points the press release mentioned were just about a Knox 1.0 software, which now was replaced by MyKnox. I don't know what Knox 1.0 is and how to get it or on which devices this is installed. All I know is, the version of Knox Container 2.0_2, which was installed on my Samsung S4 is heavily insecure.
  • @Samsung: I would really like to investigate your so called MyKnox and check if all your security measurements you mentioned in the press release are true. But please let me know what kind of device I have to buy to get the secure version :).

What is Samsung Knox:

Samsung phones, like the Samsung Galaxy S4, are shipped with a preinstalled version of Samsung Knox. Samsung advertises Knox with the following:

"KNOX Workspace container improves the user experience, providing security for enterprise data by creating a secure zone in the employee’s device for corporate applications, and encrypting enterprise data both at rest and in motion. KNOX Workspace container provides users with an isolated and secure environment within the mobile device, complete with its own home screen, launcher, applications and widgets for easier, more intuitive and safe operation. Applications and data inside the container are separated."


Searching around the internet to find specific information about Samsung Knox were not satisfying, as Samsung Knox is not open source. This was the reason to investigate Samsung Knox a little bit and lead to this analysis. Also today I read an article that the US government certified the use of Samsung Knox for their work and this was the reason to publish my analysis.


Setup:

The Samsung phone comes preinstalled with two apps: Knox and Knox EMM. Knox EMM is a enterprise cloud-based management solution for mobile devices which was not part of this analysis. Focus was set to the Knox app, which provides the Knox Container and a seperate (secure) home screen with own apps. The setup for Knox is quite easy, you just have to set a password and a pin for the Knox App. Looking at the system internals, Knox installs quite a lot of stuff on your phone. Knox related apps in /data/data/:


com.samsung.klmsagent
com.samsung.knoxemm.mdm
com.sec.knox.app.container
com.sec.knox.containeragent
com.sec.knox.eventsmanager
com.sec.knox.seandroid
com.sec.knox.store

Additionally all apps which are installed in the new Knox home screen are located in the standard app installation folder /data/data/ and come with the prefix: com.sec.*. Listing all of them here would be too much. After a typical Knox installation there are 139 apps and services installed with the prefix com.sec.*
Looking a bit deeper in the system, Knox is distributed through the whole system and stores data in a couple of different locations, for example: the encrypted container itself will be stored in /data/.container_* and/data/container/.sdcontainer_1.* Different files and databases for settings are stored in /data/system/secure_storage and /data/system/container.


Analysis:

 

Each analysis of a mobile app starts with a static analysis of the files the app stored after the setup. A good starting point for Android Apps is the app folder under /data/data/. These folders typically have the structure:

com.aPackageName 

    |- cache

    |- databases 

    |- extracted

    |- lib

    |- shared_prefs 


Especially the folders databases and shared_prefs are the ones that deserves the first attention. The ContainerAgent app of Knox (com.sec.knox.containeragent) had some interesting files stored:

Activation.xml
ContainerActivator.xml
ContainerType.xml
CreateSettings.xml
DB_BRIDGE_INIT_SYNC.xml
DB_BRIDGE_ISCHNDUOS.xml
DB_BRIDGE_ONCHANGE_CONTACTS.xml
DB_BRIDGE_ONCHANGE_EVENT.xml
KLMSLicenseStatus.xml
Pref.xml
PrivacyPolicy.xml
bno.xml
com.sec.knox.containeragent_preferences.xml
pin.xml 
 
Yes, guess what is written in the pin.xml file? The pin we had to set during the setup of Knox in cleartext!

<?xml version='1.0' encoding='utf-8' standalone='yes' ?>
<map>
    <string name="code">123456789</string>
</map>

The other files didn't reveal other interesting stuff. But back to the pin.xml file. What is the purpose of the pin in Knox anyway? If you're going to start Knox you have to provide your password to get access to the data and the Knox home screen. But there is a small button under the textfield called "Password forgotten?". By tapping it, you have to provide your pin. If the PIN is correct the Knox app will show you a little password hint (the first and the last character of your password!! + the original length of your password!). So now it is pretty obvious that Samsung Knox is going to store your password somewhere on the device! As mentioned above, Knox is not only storing settings in /data/data/, in the Folder /data/system/container there is a file called containerpassword_1.key [sic!] stored. The content is a crypted string: 72C9EE6D56CB15916A4CAB01814F978FA1E2689D (I modified the string for obvious reasons ;)).

So this looks like an AES encrypted string. No we have to decompile the apps to have a deeper look how exactly the encryption of the password works and where the key for the encryption comes from. Samsungs makes use of dex-preoptimization to strip out all classes.dex files (the java code is stored in a file called classes.dex and this file is parsed by the Dalvik JVM) in the Knox apks, thus making reverse engineering a little bit harder. To get the binaries we have to look at /system/app/ and find .odex files (an odex is basically a pre-processed version of an application's classes.dex that is execution-ready for Dalvik). odex files can be converted back into smali code, which then can be converted back to a dex file. Finally a dex file can be converted into a jar file, which can be decompiled by any Java Decompiler.

Samsung didn't make any use of code obfuscation but really tried to hide the password storage code within hundreds of java classes, inheritance and proxies. Finally in the Knox Store app the proxy IDataService was implemented which all other apps were constantly calling when handling something password related. So when saving the password the app is doing the following:


public boolean setData(String paramAnonymousString) {

    this.keyGenInput = DataService.this.mPasswordUtil.getInputForKeyGenerate();

    String str = SecureKeyLoader.getKeyForPassword(this.keyGenInput, this.bit_size);

    return DataService.this.mEncryptDecrypt.encryptAndSave(paramAnonymousString, str);

}


Let's have a look at each line and the corresponding methods:


public long getInputForKeyGenerate()
  {
    return Long.parseLong(SecureKeyLoader.getPartialString(getAndroidID()), 16);
  }
private String getAndroidID()
  {
    return Settings.Secure.getString(this.mContext.getContentResolver(), "android_id");
  }


So the input for the key is obviously the unique Android ID which every device has. The 16-Byte ID parsed as Long value is then used as an argument for the function getKeyForPassword:

 
public class SecureKeyLoader
{
  static
  {
    System.loadLibrary("mealy");
  }
  public static native String getKeyForPassword(long paramLong, int paramInt);
  public static native String getPartialString(String paramString);
} 
 
Ok, Samsung is obfuscating it more and more to hide the real key generation. The method getKeyForPassword is placed in a C written shared library called "mealy". Let's grab the library from the device and put it into a disassembler like IDA:



The binary has one hardcoded string called "out_char" with the following value: eu>q5b0KPlLwyb@*#j9?!*ehjl(LHukkA(di^S4UXAChr3B`_xf+@h*#S&wpfv&# . By looking at the code the method getKeyForPassword gets as an argument the long value of getPartialString(getAndroidID()), holding as variable the out_char String and passes both of them to the subroutine 'mealymachine'. Let's have a look at the function getKeyForPassword and the subroutine mealymachine in pseudo code:


function Java_com_sec_knox_store_SecurityManager_SecureKeyLoader_getKeyForPassword {
    r4 = r0;            //partialString androidID as long value
    r0 = r2;            //integer = 16
    r0 = mealymachine(r0, var_8, next, "eu>q5b0KPlLwyb@*#j9?!*ehjl(LHukkA(di^S4UXAChr3B`_xf+@h*#S&wpfv&#", STK29);
    r3 = *r4;
    r2 = *(r3 + 0x29c);
    r0 = (r2)(r4, r0, r2, r3);
    return r0;
}
function mealymachine {
    r6 = r0;            //partialString androidID as long value
    r5 = r1;            //var_8
    r7 = r2;            //next
    r8 = r3;            //eu>q5b0KPlLwyb@*#j9?!*ehjl(LHukkA(di^S4UXAChr3B`_xf+@h*#S&wpfv&#
    if (r1 <= 0x64) {
            r4 = 0x0;
            memset@PLT(0x2144, 0x0, 0x64);
            r1 = r4;
            do {
                    if (r4 >= r5) {
                        break;
                    }
                    r0 = r6 & 0x1;
                    r6 = r6 >> 0x1;
                    *(int8_t *)(r4 + 0x2144) = *(int8_t *)(r0 + r8 + r1);   //AndroidID + eu>q5b0KPlLwyb@*#j9?!*ehjl(LHukkA(di^S4UXAChr3B`_xf+@h*#S&wpfv&# + var_8
                    r4 = r4 + 0x1;
                    r1 = *(r0 * 0x4 + r7 + r1);
            } while (true);
            r0 = 0x2144;                                                                                                   
            *(int8_t *)(r0 + (r5 & !r5)) = 0x0;
            return r0;
    }
    else {
            r0 = 0x0;
            return r0;
    }
    return r0;
}
 
By looking at the subroutine it just adds the long value from the Android ID and the hardcoded string. The method getPartialString substractes a part out of the Android ID. Just for the clarification: every app can ask the system for the Android ID by calling: Secure.getString(getContext().getContentResolver(),Secure.ANDROID_ID);


Conclusion:

Samsung really tried to hide the functionality to generate the key, following the security by obscurity rule. In the end it just uses the Android ID together with a hardcoded string and mix them for the encryption key. I would have expected from a product, called Knox, a different approach:

  • The fact that they are persisting the key just for the password hint functionality is compromising the security of that product completely. For such a product the password should never be stored on the device. There is no need for it, only if you forget your password. But then your data should be lost, otherwise they are not safe if there is some kind of recovery option.

Recommendation:

Instead of Samsung Knox, use the built-in Android encrpytion function and encrypt the whole device. Android is using a PBKDF2 function from the encryption password you choose and never persists it on the device. Obviously you can never access the data if you forget your password, but that's the point of a good encryption.