I have been doing some security testing on an Android app. One thing I am trying to wrap my head around is API key security; particularly google Places and Maps keys. There are lots of posts that talk about the options, namely compiling keys into source, placing them in resource files, compiling them into a shared library, etc. In my particular case, the Maps key is in the manifest file, and the Places key is in a shared library. I created a signed APK to test how hard it would be to obtain and use one of the keys. I did the following:
Reverse engineered the APK using apktool,
Opened the manifest and grabbed the Maps key,
Created a fake version of the application with the same package structure as the original containing an activity with a google map fragment,
Put the Maps key in the fake manifest,
Ran the application, which displayed the map
Then I:
Created a new class in the fake app with the same package and name as the original with code to load the shared library from /data/data/[package name],
Copied the the shared library from the reverse engineered APK to the /data/data/[package name] folder of the fake app,
Ran the fake app, which then printed out the Locations API key
So in the end, without much effort, I had both keys which I could then use in a fake version of the application.
I'm sure I must be missing something. It looks like the only option for Maps is to store the key in the manifest. What is stopping someone from doing what I did? Surely it can't just be indifference. I realize that someone would probably get caught if they tried to publish their app using a hijacked API key. However, someone could create an app and have people side load it. It would be a huge disruption for customers if the company had to change a hijacked key every time someone messed with it.
I believe you need to go through the Docs for Google API keys again. There seem to have something called restrictions that should be able to help with you ensuring that your Keys are protected and not used on some other application.
I believe that restrictions prevent a request from other domains you have not included from not being able to render.
API Key best practices
There are many way to keep your API key secure. Below links are explained that how to secure your keys.Depending on your use case you can follow one of them
Using Gradle
Using NDK
Using Server Call
Related
I am developing an SDK/API that will be used by apps not written by me.
I want my code to generate a private key once and store it on the device.
This key should be unique per device, I don't mind it being erased on factory reset, and I don't need to extract it from the device.
Sounds an ideal case for the KeyStore (preferably with a StrongBox).
I do want, though, different apps to use the same key to sign (or ask my API to do so)
I could not answer two concerns:
If my API is a library linked (statically) into the app, different apps using my code wouldn't be able to use the key, because the keystore requires
If I package my API as a separate android app, and have the other apps use it using Intents, I'll have to have the user install it manually, because as far as I could tell, Android/Play does not allow for dependencies between apps.
What is the most graceful way to resolve this situation?
Looking to improved the security of my Android app to flag if the .apk has been extracted, modified, repacked and resigned. Here's article from Zdnet noting the issue link1.
The concern is if the app is targeted by hackers they could add malicious code and upload to an alternate app store and dupe users in to downloading it.
So I'm thinking code to verify a checksum of the apk or signing certificate?
I appreciate the app code could be repacked and any security code removed, but it does increase the difficulty of repacking it, maybe enough for them to try another app.
[update]I know the Google Play store licensing module offers something similar but I'm looking for something for non paid apps and other/non marketplaces.
I ended up using Dexguard (paid obfuscator for Android). It offers a module that preforms apk verification. It is simple to implement and offers better than average protection.
Here's the code to do the check:
dexguard.util.TamperDetection.checkApk(context)
The main issue is where to store the checksum of the apk to verify against given that it could to be replaced. The dexguard way is to check it locally but using other features like class/string encryption and api hiding obscure this call.
Here are some of the articles that could help you out.
Retrieving APK signature during runtime.
Self checking an APK signature.
How to check APK signature.
Use the Google licensing service It will connect with the play store to make sure the user purchased the app every few days. (you can set the amount) Also loook at ProGuard. It strips all the class, method, and variable names out of your code making it really hard to understand once its decompiled.
In order to use the Google Maps API, Google requires the MD5 fingerprint of a keystore:
To display Maps data in a MapView, you need to register for a Maps API Key
Each Maps API Key is uniquely associated with a specific certificate, based on an MD5 fingerprint of the certificate
You can register multiple certificates under your developer identity
You can get a temporary Maps API Key based on your debug certificate, but before you publish your application, you must register for a new Key based on your release certificate and update references in your MapViews accordingly
We have multiple people who are going to be using the Google Maps API and we are using Subversion to track everything. It seems a lot easier if all the developers simply point at the same keystore but the Eclipse IDE doesn't seem like it has a way to point at more than one keystore and each developer works on multiple projects.
Is there a way to get Eclipse to use a keystore in the current Subversion repository without being a hassle (i.e. without having to change preferences all the time)?
Or should there be a new SVN repository dedicated solely to managing the debug keystore for all of our devs?
How are you doing this at your organization?
Basically, default debug keystore is stored in
/Users/{NAME}/.android/debug_keystore
Set SVN Repository and Checkout to the computer, which contains the file “debug.keystore”
In Eclipse, File->Preference->Android->Build.
Set “Custom debug keystore” to “debug.keystore” file in SVN Checkout Directory
http://chrislee.kr/wp/2010/12/31/share-google-android-api-key-in-eclipse-with-other-team-members/
It is easier if you add all developers debug keys to google-play-services and generate one Api key for all of them. Much more is complicated for all of developers to get debug key from repo and setup it in eclipse. Google Maps Api v2 for sure allows to add more then one SHA1;com.package.name lines to get one Api key.. (btw that is the way to do it..)
Puting maps key in string.xml resource file is probably the most unsecure solution. Apk can be relatively easy reverse engineered and the easiest files to read are resources (among those xml files)
Making repo just for debug keys is IMHO way to overhead...
maybe it is just me..but..
I hope this answer really helped you and others.. ;)
We ended up putting the Maps key into the strings.xml file and then referencing it that way. There are a couple of different ways to start a MapActivity in our application. So that makes it easy to go live when we are ready - just replace the key in the one location and then it is basically ready to submit to the Market.
We also set up a single Subversion repository whose sole purpose in life is to house the debug keystore and Maps API keys and anything else in the future that is keystore-specific. All of the developers now point at that single debug keystore from within Eclipse and the app works like a charm.
The apps we write will soon be enhanced by downloadable "packages" using the in-app purchase API. We would like therefore to start securing our content which we wish to allow the users to download/extract onto their memory card (so as to not use up internal memory for our large applications), however, we need to secure the files somehow so that they can't simply be taken from the SD.
Can anyone suggest some possible/simple/common techniques used to do so on Android?
You'll want to look into ProGuard, it's pretty well integrated with ADT. An easy way to get a good ProGuard config file is to create a new Android project in Eclipse, as the newer versions of ADT automatically make one for you. It is used when you right click the project and use Android Tools>Export
I'd think you'd probably want to generate a hash based on some unique device identifier and a strong key of your choosing. A unique identifier for the device can be generated using the technique discussed in this answer. Have the App transmit that hash to your server, and encrypt the package before (or as) it is sent to the user using this hash as a key. Your app will decrypt the data as it is read by generating the key on demand (the same way it was initially generated). Have a look at the MessageDigest class and the javax.crypto package in the API.
This cannot be impossible: We have four developers on an android app that uses the google maps api. We have generated a maps key that works for the one who generated it. All the others, however, see a tiled MapView without the actual map. Since my debug.keystore was used to generate, I was suspecting that the others need the same keystore. So I moved it into the repository so that everyone has a copy of it now. Then, everyone pointed eclipse towards that keystore using the custom keystore setting in Android->Build. This still does not work. What do we have to do? Surely we don't have to each use our own key and keep replacing it after every pull?
This site (and the web in general) contains tons of information on Google Maps API keys, but none answered my question unfortunately.
In year 2013 for V2 you can include as many keystores app as you like. For me it was debug and production keystores. Just follow process described here (this is a common process). When you create Android Key in Google API Console specify each fingerprint;package.name per line. E.g.:
BB:0D:AC:74:D3:21:E1:43:67:71:9B:62:91:AF:A1:66:6E:44:5D:75;com.example
94:66:06:01:12:27:AC:39:BB:44:90:41:40:86:88:3D:96:A7:99:A9;com.example
That's it! Now you have 1 API Key for 2 keystores.
Rather than trying to point Eclipse to a different keystore, just replace your local debug.keystore with the shared copy.
In https://console.developers.google.com/?hl=IT, where your app is registered and where one of the teammates has created the key for the first time, first of all you have to go to your project. Then select your key and, between the options of the key, choose "No restrictions". Now you all can see Google maps in the app working.