34

An Android/Iphone app will be accessing application data from the server. [Django-Python]

How can I secure the communication with the mobile app ?

Expectation : Secure enough for sensitive information like passwords, there shall be no direct way of decryption except brute-forcing.

My requirements :

  • Authentication [Only the app is authorized]
  • Integrity [Messages should not be modified in between]
  • Privacy [Communication should not be readable if sniffed]

My effort:

  • SSL authenticates only the Server, not the client.
  • I can-not use a symmetric encryption [Provides only Privacy]
  • Digital signature is not possible [Lacks Privacy]
  • PGP full-fills all 3 requirements.

Problem :

  • PGP requires to store keys on client app.
  • There seems to be no assuring way of securing keys on client app.
  • If the key is out, then PGP or Symmetric encryption are equally vulnerable.
  • Reverse-Engineering PGP keys or symmetic keys is equally hard.
  • In that case PGP is a non-sense burden on the mobile processor.
  • OAuth is again useless, since it also have a client key.

So, how can/should I move forward on this ? How does the industry deals with this ?

Should I implement casual approach :

  • Use simple SSL and cross my fingers ?, since authentication is not possible if the keys are stolen? (Only server authentication is possible with this)

Update:

Conclusion was to use AES, since if I can keep the key secure then I am as good as SSL. Plus I can keep changing the key over-time for better security. Contribute if you think there is a better way, do read the entire post before posting.

Yugal Jindle
  • 44,057
  • 43
  • 129
  • 197
  • You do not have integrity with AES: http://security.stackexchange.com/questions/9437/does-symmetric-encryption-provide-data-integrity – schlamar Jun 18 '12 at 10:06
  • I can encrypt a `SHA1` with the data to implement integrity with `AES`, that can be easily verified when decrypted at receiver end. – Yugal Jindle Jun 18 '12 at 10:33
  • You are still more vulnarable. If you use AES and there is a disclosure of the key, the attacker can read every communication as MITM. With SSL, an attacker can just fake an authorized client and not read the communication of other clients. – schlamar Jun 18 '12 at 13:53
  • Well, the whole question revolves around the state of loosing the key. If the private key is compromised then the attacker can read and fake anything. In Web SSL makes sense since its on your machine, the key. But in case of mobile it has to be kept in the executable used by a potential hacker to access core parts of the server for malicious needs. That is the point of the whole question. – Yugal Jindle Jun 19 '12 at 04:50
  • SO, if the key is compromised both SSL and AES stands equally unsafe, then why to spend extra CPU for same level of security. [ Note I am keeping the case of bruteforcing aside ] – Yugal Jindle Jun 19 '12 at 04:51
  • No, that is not true. With SSL, an attacker cannot fake a server and therefore not perform a MITM attack (assuming you have different certs for client and server). He can fake a client, but not read the communication of others! – schlamar Jun 19 '12 at 05:46
  • Right, he can-not read the communication of others in `AES` as well considering mobile application as the client. Since the mobile operator will have their own encryption on the communication. He can only do that if he has access to the mobile device itself. – Yugal Jindle Jun 19 '12 at 06:27
  • That's why I don't see a difference in using `SSL` for mobile client. – Yugal Jindle Jun 19 '12 at 06:27
  • That's not true for a Wi-Fi connected phone... – schlamar Jun 19 '12 at 07:31
  • Well.. But the entry point lies with compromising the key in the first place. That is equally unsafe in both `SSL` and `AES`. And then it can be protected from WIFI and stuff only if I use asymmetric encryption, for that how can I pack separate private keys inside the same application binary when I have to offer it on the appstore ? – Yugal Jindle Jun 19 '12 at 09:07
  • What's your goal? Do you want to protect your API from unauthorized access? If this is the point here just implement that on top of the network layer (custom login, google auth, ...). If that's not the point you should make the requirements more clear. – schlamar Jun 19 '12 at 11:24
  • My goal is simply to secure the communication, now I compare `SSL` & `AES`. `SSL` and `AES` are both equally insecure if key is compromized [ Bruteforcing not considered ], but `SSL` is heavier on CPU for a mobile device. So, I was wondering if I am wrong in using `AES` with all the arguments stated above. – Yugal Jindle Jun 19 '12 at 11:52
  • And I have already pointed out that `SSL` is more secure if the key is compromised (malware on phone or attacker on Wi-Fi cannot read the communication). Any reference that `SSL` is actually slower than `AES`? I don't think this is measurable (except the handshake). Depending on the SSL configuration, the encryption might be faster (for example if RC4 is used). – schlamar Jun 19 '12 at 12:28
  • Indeed `SSL` is far slower than `AES`, what I found googling. But I can't distribute a separate private key inside each binary in case of mobile as a client. [ That I have said before ] I know `SSL` would have been better if I could have been able to distribute separate keys with each binary. But in that case as well I will have to maintain separate public keys on the server and then how to recognize which one needs what key ? `SSL` is used on http since the public and private keys are generated on the fly and die off once the connection is closed. It doesn't seems practical in this case. – Yugal Jindle Jun 20 '12 at 01:59
  • Show me references of your google search. As already said, what you **really** want is a auth solution on top of the encrypted communication! – schlamar Jun 20 '12 at 05:59

3 Answers3

23

You're working on bad information. SSL can absolutely authenticate the client, it's just not something that is done for the bulk of SSL as the protocol is (or, atleast was) typically used to protect e-commerce sites where authentication of the server was important but doing so with the client was not important and/or not feasible. What you want to do is employ mutually-authenticated SSL, so that your server will only accept incoming connections from your app and your app will only communicate with your server.

Here's the high-level approach. Create a self-signed server SSL certificate and deploy on your web server. If you're using Android, you can use the keytool included with the Android SDK for this purpose; if you're using another app platform like iOS, similar tools exist for them as well. Then create a self-signed client and deploy that within your application in a custom keystore included in your application as a resource (keytool will generate this as well). Configure the server to require client-side SSL authentication and to only accept the client certificate you generated. Configure the client to use that client-side certificate to identify itself and only accept the one server-side certificate you installed on your server for that part of it.

If someone/something other than your app attempts to connect to your server, the SSL connection will not be created, as the server will reject incoming SSL connections that do not present the client certificate that you have included in your app.

A step-by-step for this is a much longer answer than is warranted here. I would suggest doing this in stages as there are resources on the web about how to deal with self-signed SSL certificate in both Android and iOS, both server and client side. There is also a complete walk-through in my book, Application Security for the Android Platform, published by O'Reilly.

  • This is definitely something that I was missing. Now, I don't know much about SSL on client-side. Though, I will explore keytool for Android but I guess for that as well we would require to save a certificate on client-side. Since, there is a tool i.e. `keytool` on android, so is there a mechanism to save the certificate securely ? (Since, android knows that this info is sensitive to the app) – Yugal Jindle Jan 10 '12 at 14:08
  • Going by your profile, you are the perfect guy to answer this question. – Yugal Jindle Jan 10 '12 at 14:11
  • 3
    @jeffsix Nice plug. And a copy-paste from http://stackoverflow.com/questions/8708849/how-would-i-protect-a-private-api/8713113#8713113 I thought I had seen this answer before... – Nikolay Elenkov Jan 10 '12 at 14:53
  • 2
    The certificate, and private key, are absolutely saved securely...encrypted with a password. Now, your app needs to have that password to access it so that's an inherent insecurity but you've got to have the access point somewhere. :) Good luck. –  Jan 11 '12 at 03:49
  • 1
    @NikolayElenkov And the answer is just as correct here. Mutually authenticated SSL is a solution to a lot of common use-cases...I just hope that more and more developers realize this. –  Jan 11 '12 at 03:51
  • @jeffsix Sir, again it boils down to a `password` that one has to keep safe. So, if the `password` is reverse-engineered then, again SSL will proof to be a stupid burden. So, why not simply use AES and try safe guarding the `secret_key`, if that is kept secure then its as secure as SSL except replay attack that I don't require. Isn't it ? – Yugal Jindle Jan 11 '12 at 04:54
  • Yes, you need to protect something (a password in this case). You will ALWAYS need to protect something and yes, that something can always be reverse engineered. However, SSL/TLS is a mature and tested protocol that provides services other than simply encrypting the data. I do not believe that choosing a well-tested, mature, industry-standard protocol that is designed for exactly the situation you describe here is a "stupid burden." But, your opinion may vary. –  Jan 11 '12 at 14:59
  • @jeffsix You have a point. Let me put it this way, if `password` is compromised then, can SSL/TLS protect any better than simple AES ? – Yugal Jindle Jan 12 '12 at 05:03
  • Nope. You always need a secret on the client (be it stored on the client or entered by the user upon use) and if that secret is compromised, then whatever transport protection you're using is compromised as well. –  Jan 12 '12 at 20:28
  • So, conclusion is simple AES is as good as SSL/TLS if `password` is kept secret. [Assuming AES and SSL are equally difficult to brute-force] Now, the question remains, on which one is difficult to brute-force [And how much]? – Yugal Jindle Jan 13 '12 at 02:22
  • If you're convinced of this, then I'm going to stop trying to convince you otherwise. Good luck. –  Jan 13 '12 at 11:55
  • In that case.. I will keep looking for the solution. – Yugal Jindle Jan 13 '12 at 13:43
  • As an aside, be careful using the Python urllib2 library for this. Contrary to expectation, it will *not* check the certificate when starting an SSL/TLS connection. – Charles Merriam Jun 12 '12 at 05:16
  • @YugalJindle You completely missed the point. SSL is a well tested industry standard developed and analysed by experts. Yes, you have to keep the key secret, but each instance of the app will have its own key, right? Just revoke compromised keys. Using a standard solution will become handy when Android integrates a crypto chip. – Alex Chamberlain Jun 12 '12 at 06:58
  • Well, how will you package apps to have different keys for each download from the webstore ? – Yugal Jindle Jun 12 '12 at 07:15
  • I've only dealt with mutual authentication on the web, so you'll have to work out the details. There must be a way at installation for a certificate to be generated. When the user first signs in, you can submit this certificate to the server for signing? – Alex Chamberlain Jun 12 '12 at 07:38
  • That is what I see as an bottle-neck in this case.. ! – Yugal Jindle Jun 12 '12 at 10:52
  • If this was a mutual authentication scenario, then we have control on both sides. The problem more of is that we don't have any control on the client's end. – Yugal Jindle Jun 12 '12 at 10:53
5

SSL does have two way authentication as already mentioned by the other commenters. But, I do not think you even should try to authenticate the client, aka the app. You only authenticate the user (resource owner in Oauth terms) not the agent or client.

It is a fact that mobile apps cannot hold any secrets. So never put certificates/ passwords on the device. Typical bad example would be to save the username and password in some system keystore, such as IOS keychain. If the app user does not set password on the phone, the entire keystore is saved in plain text and anyone can dump all information. Embed a certificate in the app is almost equally bad as unlike a server, mobile phone is not locked in a computer room. People do lose them.

On that basis, you need a token based solution, so that the app does not need to hold secrets. You pass on the secrets (user login credentials) and clear them out from memory immediately. You only need to hold the token, which will be short lived (expires in 30 mins etc.)

Oauth 2.0 Implicit flow is designed to solve this problem. However, its a far from perfect. And there are some fundamental issues with the Oauth 2.0 spec. Especially, implementing this flow requires the app to use UIWebView (embeded browser), which itself can be insecure and bad user experience. So this pretty much eliminates all redirection based flows. The only well known app that uses OAuth 2 redirection flow is facebook, and its done badly.

OAuth 2.0 Resource Owner flow is one option. With this flow, your entire systems security level can be as high as B2C solution -- browser based online banking solution as an example. This means anyone with the username password will be able to access the resources on the server -- the same level of security for a browser based solution.

However, you still need to be careful, as mentioned before, the OAuth 2 spec has some fundamental issues -- in this case, you cannot follow its spec to implement the token refresh logic -- that typically involves using a never-expire refreshing token-- which can be seen as Google's OAuth 2 implementation. That token then becomes a secret itself -- defeats the purpose of using OAuth.

One workaround is to auto-renew the token based on last activity.

Anyway, mobile app security is not a new topic at all but sadly we still do not have any standard tools/mechinisms to solve those unique challenges.

Thats why banks pay millions to do their mobile banking solution and yet they still fail(http://hothardware.com/News/Mobile-Banking-Apps-for-iOS-Vulnerable-to-Man-in-the-Middle-Attacks/) ;-)

Jason Wang
  • 629
  • 1
  • 8
  • 11
-1

Use client authentication with SSL or just layer your own client authentication (username/password, token, etc) on top of server-authentication SSL.

(Edit: Moving the comment here, since it won't fit as a comment)

To elaborate a bit, any authentication info needs to be stored or entered in the app. If you have people enter the password each time, you don't need to save it, but that's clearly inconvenient. You can encrypt it with a device-specific key, so it's not visible on rooted devices. With a private key, you need to either protect it with a user entered password (see above) or have it protected by the system. That is only available since Android 4.0 (ICS) with the public API to the system keystore, the KeyChain class. In this case, the user needs to unlock (using pattern/password or PIN) the phone to access the keystore.

Nikolay Elenkov
  • 52,576
  • 10
  • 84
  • 84
  • Please elaborate.. and please refer to requirements and explain a bit how are they getting satisfied. – Yugal Jindle Jan 10 '12 at 06:21
  • Username and password are again to be stored on the app, that I am assuming will be stolen like the keys. – Yugal Jindle Jan 10 '12 at 06:22
  • How do you authenticate the client with SSL ? – Yugal Jindle Jan 10 '12 at 06:23
  • 1
    Is it that hard to Google "SSL client authentication"? With a client certificate and private key. – Nikolay Elenkov Jan 10 '12 at 06:40
  • I am searching on it already. I wanted you to elaborate conceptually since client-side SSL is new to me. – Yugal Jindle Jan 10 '12 at 14:09
  • You need to research a bit, or, apparently, buy a book :) See updated answer. – Nikolay Elenkov Jan 10 '12 at 17:12
  • Good answer (or update, I guess :)). The use of KeyChain in ICS devices is a good idea and does provide much greater protection for the secret that you're using to secure the client-side keys. For anything before ICS, it's going to be a "make it as hard as you can" approach as @NikolayElenkov describes. –  Jan 11 '12 at 15:02