iOS -- Technique for securing SOAP API credentials embedded in binary - ios

The answer proposed in Embed API credentials in iOS code is not an option for me.
My app communicates with a back-end SOAP API over HTTPS. My API credentials are sent in every request.
I don't have control over the server implementation, so I'm not able to add an intermediary authentication server and migrate to a token-based implementation.
Because I have to embed my credentials with my app's binary (I understand that this is far from ideal, on principle), i am looking for best practices to make my credentials as secure as is possible.
From what I've read, I've gathered:
Don't include credentials in an external file (such as a .plist)
Don't include credentials as simple NSString * const declarations. (Is using a char * safer?)
Don't do something obvious, like put my credentials in an Objective-C singleton called AuthenticationKeyManager
I also saw this article: http://applidium.com/en/news/securing_ios_apps_debuggers/
=> tldr: add release-mode code in the main.m to prevent the app from running if a debugger is attached
Note: I am able to implement SSL pinning.
Are there any other measures I can take to safeguard my access credentials?

There is described how create and use encrypted plist: http://aptogo.co.uk/2010/07/protecting-resources/
But aes key from it is stored in static NSString *sharedKey;

Related

Where should I store my API key in IOS app [duplicate]

I want to store a secret key ("abc123") that I will use in the header of my REST API requests. My server will check this secret key. If it matches "abc123", then allow the request to be made.
I'm thinking about a simple solution like:
let secret = "abc123"
But are there going to be any downfalls to this?
Crazy as it sounds, this is probably the best solution. Everything else is more complicated, but not much more secure. Any fancy obfuscation techniques you use are just going to be reverse engineered almost as quickly as they'll find this key. But this static key solution, while wildly insecure, is nearly as secure than the other solutions while imposing nearly no extra complexity. I love it.
It will be broken almost immediately, but so will all the other solutions. So keep it simple.
The one thing that you really want to do here is use HTTPS and pin your certificates. And I'd pick a long, random key that isn't a word. Ideally, it should be a completely random string of bytes, stored as raw values (not characters) so that it doesn't stand out so obviously in your binary. If you want to get crazy, apply a SHA256 to it before sending it (so the actual key never shows up in your binary). Again, this is trivial to break, but it's easy, and won't waste a lot of time developing.
It is unlikely that any effort longer than an hour will be worth the trouble to implement this feature. If you want lots more on the topic, see Secure https encryption for iPhone app to webpage and its links.
By hardcoding the string in your app, it's possible for attackers to decrypt your binary (via tools like dumpdecrypt) and get your string without much trouble (a simple hexdump would include any strings in your app).
There are a few workarounds for this. You could implement an endpoint on your REST API which returns your credentials, that you could then call on launch. Of course, this has its own non-trivial security concerns, and requires an extra HTTP call. I usually wouldn't do it this way.
Another option is to obfuscate the secret key somehow. By doing that, attackers won't be able to instantly recognize your key after decryption. cocoapods-keys is one option which uses this method.
There's no perfect solution here – the best you can do is make it as difficult as possible for an attacker to get a hold of your keys.
(Also, be sure to use HTTPS when sending requests, otherwise that's another good way to compromise your keys.)
While in-band tokens are commonly used for some schemes, you're probably eventually going to implement TLS to protect the network traffic and the tokens. This as Rob Napier mentions in another reply.
Using your own certificate chain here allows the use of existing TLS security and authentication mechanisms and the iOS keychain, and also gives you the option of revoking TLS credentials if (when?) that becomes necessary, and also allows the client to pin its connections to your servers and detect server spoofing if that becomes necessary.
Your own certificate authority and your own certificate chain is free, and your own certificates are — once you get the root certificate loaded into the client — are just as secure as commercially-purchased certificates.
In short, this certificate-based approach combines encryption and authentication, using the existing TLS mechanisms.
It looks like you are using access tokens. I would use Keychain for access tokens. For Client IDs, I would just keep them as a variable because client ids don't change while access tokens change per user, or even per refresh token and keychain is a safe place to store user credentials.
I have used the PFConfig object (a dictionary) that allows you to retrieve in your app values of variables stored as Server environment parameters.
Similar to the environment variables that can be retrieved using ENV in web sites server side programming like Ruby or PHP.
In my opinion this is about as secure as using Environment variables in Ruby or similar.
PFConfig.getConfigInBackgroundWithBlock{
(config: PFConfig?, error: NSError?) -> Void in
if error == nil {
if let mySecret = config["mySecret"] as? String {
// myFunction(mySecret)
}
}

In iOS, how can I store a secret "key" that will allow me to communicate with my server?

I want to store a secret key ("abc123") that I will use in the header of my REST API requests. My server will check this secret key. If it matches "abc123", then allow the request to be made.
I'm thinking about a simple solution like:
let secret = "abc123"
But are there going to be any downfalls to this?
Crazy as it sounds, this is probably the best solution. Everything else is more complicated, but not much more secure. Any fancy obfuscation techniques you use are just going to be reverse engineered almost as quickly as they'll find this key. But this static key solution, while wildly insecure, is nearly as secure than the other solutions while imposing nearly no extra complexity. I love it.
It will be broken almost immediately, but so will all the other solutions. So keep it simple.
The one thing that you really want to do here is use HTTPS and pin your certificates. And I'd pick a long, random key that isn't a word. Ideally, it should be a completely random string of bytes, stored as raw values (not characters) so that it doesn't stand out so obviously in your binary. If you want to get crazy, apply a SHA256 to it before sending it (so the actual key never shows up in your binary). Again, this is trivial to break, but it's easy, and won't waste a lot of time developing.
It is unlikely that any effort longer than an hour will be worth the trouble to implement this feature. If you want lots more on the topic, see Secure https encryption for iPhone app to webpage and its links.
By hardcoding the string in your app, it's possible for attackers to decrypt your binary (via tools like dumpdecrypt) and get your string without much trouble (a simple hexdump would include any strings in your app).
There are a few workarounds for this. You could implement an endpoint on your REST API which returns your credentials, that you could then call on launch. Of course, this has its own non-trivial security concerns, and requires an extra HTTP call. I usually wouldn't do it this way.
Another option is to obfuscate the secret key somehow. By doing that, attackers won't be able to instantly recognize your key after decryption. cocoapods-keys is one option which uses this method.
There's no perfect solution here – the best you can do is make it as difficult as possible for an attacker to get a hold of your keys.
(Also, be sure to use HTTPS when sending requests, otherwise that's another good way to compromise your keys.)
While in-band tokens are commonly used for some schemes, you're probably eventually going to implement TLS to protect the network traffic and the tokens. This as Rob Napier mentions in another reply.
Using your own certificate chain here allows the use of existing TLS security and authentication mechanisms and the iOS keychain, and also gives you the option of revoking TLS credentials if (when?) that becomes necessary, and also allows the client to pin its connections to your servers and detect server spoofing if that becomes necessary.
Your own certificate authority and your own certificate chain is free, and your own certificates are — once you get the root certificate loaded into the client — are just as secure as commercially-purchased certificates.
In short, this certificate-based approach combines encryption and authentication, using the existing TLS mechanisms.
It looks like you are using access tokens. I would use Keychain for access tokens. For Client IDs, I would just keep them as a variable because client ids don't change while access tokens change per user, or even per refresh token and keychain is a safe place to store user credentials.
I have used the PFConfig object (a dictionary) that allows you to retrieve in your app values of variables stored as Server environment parameters.
Similar to the environment variables that can be retrieved using ENV in web sites server side programming like Ruby or PHP.
In my opinion this is about as secure as using Environment variables in Ruby or similar.
PFConfig.getConfigInBackgroundWithBlock{
(config: PFConfig?, error: NSError?) -> Void in
if error == nil {
if let mySecret = config["mySecret"] as? String {
// myFunction(mySecret)
}
}

iOS App Security Best Practices (API Keys, Constants, WS URLs, Credentials)

What are the best practices to add the extra security in iOS App so Attackers/Hackers can not easily find the Secure Private Keys, Constants strings inside the code.
P.S: I found some other related questions which were answered partially or missing some aspects of this question,
so I've added detailed question along with some findings below so
anyone can get benefit from this thread later on.
100% Security for any Application not possible but we can try to make the attacking/cracking of iOS App as much harder as possible by implementing more security so that the App can not be cracked/hacked easily.
Following are few data which should be more secure
All User Credentials (username, password etc)
API Keys, Private Keys, Tokens, WebService URLs/EndPoints etc (Constant/Hardcoded Variables)
WebService Requests, Response (Network Layer)
I've already stored all the user credentials on KeyChain,
1. Is there any approach to encrypt the .ipa file so decompiling/reverse engineering of iOS Binary App becomes more
harder?
.
2. How to store any Constant HardCoded API Key/Token so even if the App is decompiled/cracked successfully by crackers ; the Constant API
keys/Tokens should be difficult to retrieve. (Assume that we have
already encoded/encrypted the keys and we we are decoding it every-time
before usage)
Following are few findings in my mind at the moment but I'm not sure which approach is better to achieve this or if there is any other standard approach then kindly advice:
Store all Hard coded Constants API Keys after encryption/encoding and when it is required it must be decrypted/decoded on demand.
Store Confidential Constants Variables as HEX/hashed Values and do not store any plain text in the Constants directly.
Obfuscation
inside the main(int argc, char * argv[]) add following lines of code to terminate the App if anyone tries to debug it using some Decompiling/Debugging tools. (not sure whether Apple will reject the app because of this or not)
disable_gdb();
Looking forward for any suggestion or best practices to make iOS App more secure.

Parse.com REST API authentication

Parse.com's REST API docs (https://www.parse.com/docs/rest) say: Authentication is done via HTTP headers. The X-Parse-Application-Id header identifies which application you are accessing, and the X-Parse-REST-API-Key header authenticates the endpoint. In the examples with curl that follow, the headers are stored in shell variables APPLICATION_ID and REST_API_KEY, so to follow along in the terminal, export these variables.
I am building a Sencha Touch app as a native app on iOS and Android using Phonegap, and I was wondering whether it is secure to expose these keys to the client while making the REST calls?
Also, can someone explain to me how does security work in this scenario? Help is much appreciated! Thanks!
Without phonegap , in a proguard , post processed android apk , the string values of the 2 headers you mention are exposed client-side . not a big issue. TLS covers the http header values during network leg and far more important for app security, you have Full ACL at the DB row level(parse/mongo) contingent on permissions of 'current user()'. So with no access to logon, some outsider doesn't have any more than obfuscated string value to an app-level access token.
. One odd thing is that with parse the lease time on the client-side token value foapi key is permanent rather than say a month.
Parse REST security is robust n well executed.
Can't speak to what PG framework offers in obfuscate/minify/uglify area but you should check that.

How to handle https for iOS client

We know that https is different with http by encrypting the content over http tunnel, simply speaking.
For the web browser, since user accept the permission from the popup alter dialog, the browser will get the keys from installed certificates and do the job so on.
For iOS client development, how to handle the digital certificate, and get the public key and encrypt the content via the public key ? thanks,
( By the way, AFnetworking is the famous open source project for iOS developer to handle the http stuff, but seems like that it does not handle the https. (correct me if wrong ) )
NSURLConnection and NSURLSession are the underlying classes used by all HTTP iOS libraries. These two classes does the HTTPS handling for you. Nothing for you to worry about.
Then, you can use libraries as AFNetworking or Hermod that work on top of these basic iOS classes.
AFNetworking is the most popular one.
Hermod is my preferred. It is a new library built on top of AFNetworking and its API is much simpler and easy to use. Also, it has built-in support for OAuth.
It's already done for you.
AFnetworking, the underlying iOS network library it's built on, NSURLConnection and pretty much every networking library (eg, ASIHTTP, etc) all handle the https protocol for you transparently.
Indeed, the very first line on the front page of the AFNetworking github page is an https example:
NSURL *url = [NSURL URLWithString:#"https://alpha-api.app.net/stream/0/posts/stream/global"];

Resources