Is it possible to distribute a populated keychain with an application - iphone

I am working on an application that uses a private web service.
We currently use a bundled client certificate to enable 2-way SSL connectivity however the password for the certificate is in the code and it is a concern that this could be de-compiled and used with the (trivially)extracted certificate file for nefarious purposes.
Is there a method by which I can pre-load a password into the application keychain for distribution with the app so that the password is never left in the open?

No matter how you put your password into your binary, there will be someway to exploit this, be it with debugging tools, code analysis etc.
You better treat your web service as open... maybe unlikely to get not properly authorized requests in the very next future, but basically you give away access to the public.
Keychain should be encrypted with user specific key, and this you obviously cannot do - or you would be able to read everyones data anyway.
If you really need to protect it, you probably need user accounts on your server... if this is more secure than obscurity it up to you.

Related

Advice on implementing web server security in iPhone app

I have a relatively successful app in the app store that allows people to view metrics on their iDevice using a JSON file hosted on the their server. The app has a simple settings screen in which you simply type the URL of your JSON file and the app takes care of visualising the data in the file. I use AFNetworking for this.
For example the URL might be: http://www.mylargecompany.com/factorykpi.json
Customers are now coming back to me and asking for the ability to connect to their servers more securely. Problem is there is a myriad of ways you can secure your server.
I need some advice. What kind of standard security features would I need to build into my app. I am confused by OAuth, HTTPS, etc.
I believe OAuth would mean the customers server would have to use it? Can you make a generic OAuth login screen in an app or do you need to know which web server you are connecting to authenticate.
Any advice on even the most basic of security measure would be very welcome!
Regards,
MonkeyBusiness
Security is really a very broad topic. There is no short answer. In any case, both web service and client app need to implement security mechanisms. I would recommend, you provide both the web service and client app.
You likely need some user login with a password, "server verifies user identity" and "client verifies server identity" using certificates. Then you utilize HTTPS which ensures to transport confident data in a secure way. The web service should be implemented with one of the well known web application frameworks since security is a scary business, and tricky. Implementing everything yourself, might end in a suboptimal insecure application.
You should now read more about the complex topic and come back when you have specific questions.
... most basic would be to use https, which would secure the transaction, but anybody accessing the same link would be able to access the same data. Thus you will need some kind of authentication, starting with a simple secret key passed as POST request, username and password and/or via certificates.

Storing authentication token on iOS

I am building an iOS application and the user authenticates with my web service. I don't want them to login every time the app launches (the token lasts a month). So I'd like to cache this on the device somewhere.
What's the best way to do this, securely?
Can I just rely on the app remaining suspended and keeping the token in 'memory'?
2 options
Make use of NSUserdefault(store as access token or textfield inputs[Remember me option])
Keychain access(recommended) for doing the job.
NSUserdefaults is not secure for storing such credible values which is for authentication purpose.Keychain on the other hand is made to do this,safe and secure.
You can't rely that iOS will keep your application forever in the memory. So, you have to save the token to persistent storage at some point.
Look at Keychain Service for iOS. This is the best place to store things like passwords, tokens and other keys.
You can't do it "securely." A token is public knowledge, and as soon as its on your device a hacker could gain access to it no matter what you try to do to protect it. Putting it in the keychain won't change this fact. Even if you store it there, which would make it secure while it's in there, they can simply wait until it expires then snag the next one when it comes in over the wire next time. Your access tokens aren't the thing you need to worry about securing, because you can't, in fact, do that in a mobile environment.
What this means is that you can store it anywhere you'd like. NSUserDefaults is fine, the keychain is fine, a database is fine, a text file in your documents directory is fine. All of them are equally secure because a determined hacker can simply wait for the right opportunity to access the data they want. You should instead worry about securing your users' authentication credentials. Make sure you store those in the keychain, and only ever communicate with your API over HTTPS to a server with a valid SSL certificate.

Can data stored in iPhone App be taken from sqlite or Preferences list file?

I am planning to store a password in my Native app (Android and iPhone). Should I store them after encrypting it ? or can I store it without any encryption? Are they really secure?
Any jailbroken iPhone will give any user access to the application's Documents folder. So, yes, it's insecure.
Additionally, if you put the password inside the code, you're still weak, as someone can decompile the program and find the key. What I'd recommend is a proxy.
For example, we have an application that connects to Facebook's API on the phone. However, we don't want to store our Facebook API private key on the phone, because then any user who reverse engineers our code could hack our Facebook application!
So, instead, we store the Facebook private key on a (secure) proxy server. When the device needs to interact with Facebook, it contacts the proxy, asks the proxy to log-in, and then the proxy gives a session key to the device to use directly with Facebook.
Certainly, it's still hackable - but you won't lose your private key in the process, and instead, the only thing your user could do is do the same things you do in your proxy server API.
Could you give us a little more information about what you're trying to do?
I would store it encrypted.
If someone would read your password he/she could simply use it. If it is stored encrypted, that person would need to decrypt it before usage.
Stored passwords are not safe at all. Determined user can root it's device and access any database and preferences. If you encypt password, your application can be decompiled to get decode function or step-executed until decrypted password is stored somewhere in process memory.
It doesn't mean you shouldn't encrypt passwords - use any symmetric encryption and initialise key in some non-trivial way (i.e. arythmetic expression). This will prevent script-kiddies and casual programmers from reading passwords. Just remember if some really want them, he will get them anyway.

How can I verify the authenticity of requests from an iphone app to my web service

I'd like to make requests from an iphone app to a web service I've built. How can I verify that requests made to the web service come from my iphone app (or indeed any authorised source) and are not forged?
I have looked at basic auth over HTTPS but is baking credentials into an application secure?
This question isn't really iphone specific; I'd like to know how to protect and authenticate requests in general.
Authentication can be asserted by presenting something you know, something you have, something you are or a combination of the three.
The iPhone doesn't have retinal or fingerprint scanners, so there are no "something you are" options available.
Client certificates work well as a "something you have" token. Most smartcards work by signing a message with an embedded certificate. When a certificate is compromised, it can be put onto a Certificate Revocation List (CRL) referenced by the webservers. Obviously, you wouldn't want to put your app's embedded certificate in the CRL -- that would deny access to all your users. Instead, you'll want users to download individual certificates to their iPhone.
After that, it's a matter of monitoring for unusual behavior to find the bad actors and adding those certs to the CRL. Two dead giveaways would be clients who send too many requests at once or from too many different IPs in too short a time.
Login/password is a simple "something you know" token. Like certificates, login/password combinations can be compromised and similar monitoring can be set up to find inappropriate behavior. The difference is compromised accounts would be marked "blocked" rather than added to a CRL.
By requiring both a client certificate and a login/password you increase the amount of effort needed to compromise an account.
Of course, you must ensure only valid accounts are added to the database. If there is an automated way to create new accounts and corresponding client certificates, then that account creation server/process becomes the easiest way for bad actors to create viable, unauthorized accounts. Requiring a real person to sign-off on accounts removes the automation process, but means a disgruntled or corrupt employee could create invalid accounts. Requiring a second person to counter-sign the account makes it harder for a single person to be an inside threat.
In short, ensuring high integrity of the clients is a process that can be made arbitrarily complex and expensive. What tools and processes you decide to deploy as the authentication scheme has to be balanced by the value of what it is protecting.
In theory, if you want the connection to be secure, the best is to have the client sign their request using a certificate. There are multiple resources about this. Look for "client certificate" on Google.
This example from Sun is in Java, but the concept is similar whatever the language.
PS: obviously, this doesn't prevent you from using other authentication methods such as passwords, etc...
PPS: Keep in mind that if someone manages to extract the certificate from your application, you are screwed either way ;-). You can imagine a store providing an individual certificate to each app and invalidating the certificates that are compromised.

OAuth secrets in mobile apps

When using the OAuth protocol, you need a secret string obtained from the service you want to delegate to. If you are doing this in a web app, you can simply store the secret in your data base or on the file system, but what is the best way to handle it in a mobile app (or a desktop app for that matter)?
Storing the string in the app is obviously not good, as someone could easily find it and abuse it.
Another approach would be to store it on your server, and have the app fetch it on every run, never storing it on the phone. This is almost as bad, because you have to include the URL in the app.
The only workable solution I can come up with is to first obtain the Access Token as normal (preferably using a web view inside the app), and then route all further communication through our server, which would append the secret to the request data and communicate with the provider. Then again, I'm a security noob, so I'd really like to hear some knowledgeable peoples' opinions on this. It doesn't seem to me that most apps are going to these lengths to guarantee security (for example, Facebook Connect seems to assume that you put the secret into a string right in your app).
Another thing: I don't believe the secret is involved in initially requesting the Access Token, so that could be done without involving our own server. Am I correct?
Yes, this is an issue with the OAuth design that we are facing ourselves. We opted to proxy all calls through our own server. OAuth wasn't entirely flushed out in respect of desktop apps. There is no prefect solution to the issue that I've found without changing OAuth.
If you think about it and ask the question why we have secrets, is mostly for provision and disabling apps. If our secret is compromised, then the provider can only really revoke the entire app. Since we have to embed our secret in the desktop app, we are sorta screwed.
The solution is to have a different secret for each desktop app. OAuth doesn't make this concept easy. One way is have the user go and create an secret on their own and enter the key on their own into your desktop app (some facebook apps did something similar for a long time, having the user go and create facebook to setup their custom quizes and crap). It's not a great experience for the user.
I'm working on proposal for a delegation system for OAuth. The concept is that using our own secret key we get from our provider, we could issue our own delegated secret to our own desktop clients (one for each desktop app basically) and then during the auth process we send that key over to the top level provider that calls back to us and re-validates with us. That way we can revoke on own secrets we issue to each desktop client. (Borrowing a lot of how this works from SSL). This entire system would be prefect for value-add webservices as well that pass on calls to a third party webservice.
The process could also be done without delegation verification callbacks if the top level provider provides an API to generate and revoke new delegated secrets. Facebook is doing something similar by allowing facebook apps to allow users to create sub-apps.
There are some talks about the issue online:
http://blog.atebits.com/2009/02/fixing-oauth/
http://groups.google.com/group/twitter-development-talk/browse_thread/thread/629b03475a3d78a1/de1071bf4b820c14#de1071bf4b820c14
Twitter and Yammer's solution is a authentication pin solution:
https://dev.twitter.com/oauth/pin-based
https://www.yammer.com/api_oauth_security_addendum.html
With OAUth 2.0, you can store the secret on the server. Use the server to acquire an access token that you then move to the app and you can make calls from the app to the resource directly.
With OAuth 1.0 (Twitter), the secret is required to make API calls. Proxying calls through the server is the only way to ensure the secret is not compromised.
Both require some mechanism that your server component knows it is your client calling it. This tends to be done on installation and using a platform specific mechanism to get an app id of some kind in the call to your server.
(I am the editor of the OAuth 2.0 spec)
One solution could be to hard code the OAuth secret into the code, but not as a plain string. Obfuscate it in some way - split it into segments, shift characters by an offset, rotate it - do any or all of these things. A cracker can analyse your byte code and find strings, but the obfuscation code might be hard to figure out.
It's not a foolproof solution, but a cheap one.
Depending on the value of the exploit, some genius crackers can go to greater lengths to find your secret code. You need to weigh the factors - cost of previously mentioned server side solution, incentive for crackers to spend more efforts on finding your secret code, and the complexity of the obfuscation you can implement.
Do not store the secret inside the application.
You need to have a server that can be accessed by the application over https (obviously) and you store the secret on it.
When someone want to login via your mobile/desktop application, your application will simply forward the request to the server that will then append the secret and send it to the service provider. Your server can then tell your application if it was successful or not.
Then if you need to get any sensitive information from the service (facebook, google, twitter, etc), the application ask your server and your server will give it to the application only if it is correctly connected.
There is not really any option except storing it on a server. Nothing on the client side is secure.
Note
That said, this will only protect you against malicious client but not client against malicious you and not client against other malicious clients (phising)...
OAuth is a much better protocol in browser than on desktop/mobile.
There is a new extension to the Authorization Code Grant Type called Proof Key for Code Exchange (PKCE). With it, you don't need a client secret.
PKCE (RFC 7636) is a technique to secure public clients that don't use
a client secret.
It is primarily used by native and mobile apps, but the technique can
be applied to any public client as well. It requires additional
support by the authorization server, so it is only supported on
certain providers.
from https://oauth.net/2/pkce/
For more information, you can read the full RFC 7636 or this short introduction.
Here's something to think about. Google offers two methods of OAuth... for web apps, where you register the domain and generate a unique key, and for installed apps where you use the key "anonymous".
Maybe I glossed over something in the reading, but it seems that sharing your webapp's unique key with an installed app is probably more secure than using "anonymous" in the official installed apps method.
With OAuth 2.0 you can simply use the client side flow to obtain an access token and use then this access token to authenticate all further requests. Then you don't need a secret at all.
A nice description of how to implement this can be found here: https://aaronparecki.com/articles/2012/07/29/1/oauth2-simplified#mobile-apps
I don't have a ton of experience with OAuth - but doesn't every request require not only the user's access token, but an application consumer key and secret as well? So, even if somebody steals a mobile device and tries to pull data off of it, they would need an application key and secret as well to be able to actually do anything.
I always thought the intention behind OAuth was so that every Tom, Dick, and Harry that had a mashup didn't have to store your Twitter credentials in the clear. I think it solves that problem pretty well despite it's limitations. Also, it wasn't really designed with the iPhone in mind.
I agree with Felixyz. OAuth whilst better than Basic Auth, still has a long way to go to be a good solution for mobile apps. I've been playing with using OAuth to authenticate a mobile phone app to a Google App Engine app. The fact that you can't reliably manage the consumer secret on the mobile device means that the default is to use the 'anonymous' access.
The Google App Engine OAuth implementation's browser authorization step takes you to a page where it contains text like:
"The site <some-site> is requesting access to your Google Account for the product(s) listed below"
YourApp(yourapp.appspot.com) - not affiliated with Google
etc
It takes <some-site> from the domain/host name used in the callback url that you supply which can be anything on the Android if you use a custom scheme to intercept the callback.
So if you use 'anonymous' access or your consumer secret is compromised, then anyone could write a consumer that fools the user into giving access to your gae app.
The Google OAuth authorization page also does contain lots of warnings which have 3 levels of severity depending on whether you're using 'anonymous', consumer secret, or public keys.
Pretty scary stuff for the average user who isn't technically savvy. I don't expect to have a high signup completion percentage with that kind of stuff in the way.
This blog post clarifies how consumer secret's don't really work with installed apps.
http://hueniverse.com/2009/02/should-twitter-discontinue-their-basic-auth-api/
Here I have answer the secure way to storing your oAuth information in mobile application
https://stackoverflow.com/a/17359809/998483
https://sites.google.com/site/greateindiaclub/mobil-apps/ios/securelystoringoauthkeysiniosapplication
Facebook doesn't implement OAuth strictly speaking (yet), but they have implemented a way for you not to embed your secret in your iPhone app: https://web.archive.org/web/20091223092924/http://wiki.developers.facebook.com/index.php/Session_Proxy
As for OAuth, yeah, the more I think about it, we are a bit stuffed. Maybe this will fix it.
None of these solutions prevent a determined hacker from sniffing packets sent from their mobile device (or emulator) to view the client secret in the http headers.
One solution could be to have a dynamic secret which is made up of a timestamp encrypted with a private 2-way encryption key & algorithm. The service then decrypts the secret and determines if the time stamp is +/- 5 minutes.
In this way, even if the secret is compromised, the hacker will only be able to use it for a maximum of 5 minutes.
I'm also trying to come up with a solution for mobile OAuth authentication, and storing secrets within the application bundle in general.
And a crazy idea just hit me: The simplest idea is to store the secret inside the binary, but obfuscated somehow, or, in other words, you store an encrypted secret. So, that means you've got to store a key to decrypt your secret, which seems to have taken us full circle. However, why not just use a key which is already in the OS, i.e. it's defined by the OS not by your application.
So, to clarify my idea is that you pick a string defined by the OS, it doesn't matter which one. Then encrypt your secret using this string as the key, and store that in your app. Then during runtime, decrypt the variable using the key, which is just an OS constant. Any hacker peeking into your binary will see an encrypted string, but no key.
Will that work?
As others have mentioned, there should be no real issue with storing the secret locally on the device.
On top of that, you can always rely on the UNIX-based security model of Android: only your application can access what you write to the file system. Just write the info to your app's default SharedPreferences object.
In order to obtain the secret, one would have to obtain root access to the Android phone.