7

I'm caching a user's authentication to whenever the Android Market Licensing ping server returns a GRANT_ACCESS pong.

Does anyone see any vulnerabilities with this strategy? I believe it is very strong, since I am obfuscating a key, and the only way to unobfuscate is to know the salt. Now, someone could conceivably open the apk and look for the salt, but this is not really the level of cracking I think is too important to worry about.

As you can see, device specific information is being added to the obfuscation technique.

// Try to use more data here. ANDROID_ID is a single point of attack. 
String deviceId = Secure.getString(getContentResolver(), Secure.ANDROID_ID); 
obfuscator = new AESObfuscator(SALT, getPackageName(), deviceId); 
mChecker = new LicenseChecker(this, new ServerManagedPolicy(this, obfuscator), BASE64_PUBLIC_KEY ); 

Next the creation of the persisted data:

 public void allow() {
   SharedPreferences settings = getSharedPreferences(PREFERENCES_EULA, 0);
   SharedPreferences.Editor editor = settings.edit();
   String uid = UUID.randomUUID().toString();
   if(!settings.contains(ACCESS_KEY)) {
     editor.putString(ACCESS_KEY,uid);       
     editor.commit();
   } 
   if(!settings.contains(OBFU_ACCESS_KEY)) {
     String obfu = obfuscator.obfuscate(uid);
     editor.putString(OBFU_ACCESS_KEY,obfu); 
     editor.commit();
   }

Then, I used another method to check the state of the cached content:

boolean isCachedLicense() {
  SharedPreferences settings = getSharedPreferences(PREFERENCES_EULA, 0);
  if(settings.contains(ACCESS_KEY) && settings.contains(OBFU_ACCESS_KEY)) {
    String accessKey = settings.getString(ACCESS_KEY, "");
    String obAccessKey = settings.getString(OBFU_ACCESS_KEY, "");
    try {
      if(accessKey.equals(obfuscator.unobfuscate(obAccessKey))) {
              return true;
      } else {
              return false;
      }
    } catch (ValidationException e) {
       e.printStackTrace();
       return false;
    }
  } else {
       return false;
  }
} 

Finally, I checked if isCachedLicense in the following locations of the LicenseCheckerCallback: @Override dontAllow, and @override applicationError. If isCachedLicense is true, then I let the user forward.

Also, full source code is located at here.

Sam
  • 7,252
  • 16
  • 46
  • 65
hunterp
  • 15,716
  • 18
  • 63
  • 115

1 Answers1

1

Obfuscation with salt is generally speaking a weak strategy. The attacker just has to figure out the salt, which is fairly straight forward to do once you know what you're looking for, and can be done without direct access to your application. Once the salt is discovered (by anyone), all of our install base has been compromised.

Your best bet is, instead of using an obfuscation algorithm with a fixed key, to use a proven encryption library+algorithm with a key that is unique to either the user or the device that you're running on.

blueberryfields
  • 45,910
  • 28
  • 89
  • 168
  • I do use a proven encryption library, see the full code for reference. – hunterp Dec 11 '10 at 02:53
  • 1
    That's one step better - the library seems to do a decent enough job. The attacker will now have to decrypt each devices' data separately, and have enough access to the device to be able to run the device specific decryptor. The global salt, though, is still a weak spot. And, since it looks like you're distributing this as a library, it has the added danger of end users not populating their own salt values. Odds are that too large a population of developers will leave it at the values you entered - I would change that to a value that's generated separately for each device. – blueberryfields Dec 11 '10 at 04:22
  • if you take a look at the reference, I already have device-specific information going into the encryption mix (I've also re-edited my question to include this info at the top) – hunterp Dec 11 '10 at 17:11