Secure Keys in iOS App Scenario, Is It Safe

Secure keys in iOS App scenario, is it safe?

Let me try to break down your question to multiple subquestions/assumption:

Assumptions:

a) Keychain is safe place

Actually, it's not that safe. If your application is installed on jailbroked device, a hacker will be able to get your keys from the keychain

Questions:

a) Is there a way to put some key into an app (binary which is delivered form AppStore) and be completely secure?

Short answer is NO. As soon as there is something in your binary, it could be reverse engineered.

b) Will obfuscation help?

Yes. It will increase time for a hacker to figure it out. If the keys which you have in app will "cost" less than a time spend on reverse engineering - generally speaking, you are good.

However, in most cases, security through obscurity is bad practice, It gives you a feeling that you are secure, but you aren't.

So, this could be one of security measures, but you need to have other security measures in place too.

c) What should I do in such case?*

It's hard to give you a good solution without knowing background what you are trying to do.

As example, why everybody should have access to the same Amazon S3? Do they need to read-only or write (as pointed out by Kendall Helmstetter Gein).

I believe one of the most secure scenarios would be something like that:

  • Your application should be passcode protected
  • First time you enter your application it requests a user to authenticate (enter his username, password) to the server
  • This authenticates against your server or other authentication provider (e.g. Google)
  • The server sends some authentication token to a device (quite often it's some type of cookie).
  • You encrypt this token based on hash of your application passcode and save it in keychain in this form
  • And now you can do one of two things:

    • hand over specific keys from the server to the client (so each client will have their own keys) and encrypt them with the hash of your application passcode
    • handle all operation with S3 on the server (and require client to send)

This way your protect from multiple possible attacks.

c) Whoooa.... I don't plan to implement all of this stuff which you just wrote, because it will take me months. Is there anything simpler?

I think it would be useful, if you have one set of keys per client.

If even this is too much then download encrypted keys from the server and save them in encrypted form on the device and have decryption key hardcoded into your app. I would say it's minimally invasive and at least your binary doesn't have keys in it.

P.S. Both Kendall and Rob are right.

Update 1 (based on new info)

First of all, have you seen in app purchase programming guide.

There is very good drawing under Server Product Model. This model protects against somebody who didn't buy new levels. There will be no amazon keys embedded in your application and your server side will hand over levels when it will receive receipt of purchase.

There is no perfect solution to protect against somebody who purchased the content (and decided to rip it off from your application), because at the end of days your application will have the content downloaded to a device and will need it in plain (unencrypted form) at some point of time.

If you are really concerned about this case, I would recommend to encrypt all your assets and hand over it in encrypted form from the server together with encryption key. Encryption key should be generated per client and asset should be encrypted using it.

This won't stop any advanced hacker, but at least it will protect from somebody using iExplorer and just copying files (since they will be encrypted).

Update 2

One more thing regarding update 1. You should store files unencrypted and store encryption key somewhere (e.g. in keychain).

In case your game requires internet connection, the best idea is to not store encryption key on the device at all. You can get it from the server each time when your app is started.

iOS API Key: Is there an actual safe way to secure your API key when making http requests?

As already pointed out by @jake you should use a token tied up only to the user instead of an Api Key for all users, but other enhancements can be done for further protect your App when doing the http requests.

The user token can be a signed JWT token and then you can enhance the security of the communication between your server and the App with Certificate Pinning in order to protect against Man in the Middle Attacks.

Other techniques like the use of OAUTH2 and hiding secrets can be used to enhance the security of your App and you can read more about it here.

Keep in mind that Certificate Pinning can be bypassed by hooking frameworks such as Xposed that contain modules specific to bypass the pinning, but still another layer of security that you should not discard once it will increase the effort necessary to hack your App on the device and will protect your App against Man in the Middle Attacks.

For ultimately security between your App and the back-end you should use an App integrity attestation service, that will guarantee at run-time that your App was not tampered or is not running in a rooted device by using an SDK integrated in you App and a service running in the cloud.

On successful attestation of the App integrity a JWT token is issued and signed with a secret that only the back-end of your App and the attestation service in the cloud are aware and on failure the JWT is signed with a fake secret that the App back-end does not know, allowing this way for the App back-end to only serve requests when it can verify the signature in the JWT token and refuse them when it fails the verification.

Once the secret used by the cloud attestation service is not known by the App it is not possible to reverse engineer it at run-time even when the App is tampered, running in a rooted device or communicating over a connection that is being the target of a Man in the Middle Attack.

You can find such a service in Approov that have SDKs for several platforms, including IOS. The integration will also need a small check in the App back-end code to verify the JWT token in order the back-end can protect itself against fraudulent use.

JWT Token

Token Based Authentication

JSON Web Tokens are an open, industry standard RFC 7519 method for representing claims securely between two parties.

Certificate Pinning

Pinning is the process of associating a host with their expected X509 certificate or public key. Once a certificate or public key is known or seen for a host, the certificate or public key is associated or 'pinned' to the host. If more than one certificate or public key is acceptable, then the program holds a pinset (taking from Jon Larimer and Kenny Root Google I/O talk). In this case, the advertised identity must match one of the elements in the pinset.

OAUTH2

The OAuth 2.0 authorization framework enables a third-party
application to obtain limited access to an HTTP service, either on
behalf of a resource owner by orchestrating an approval interaction
between the resource owner and the HTTP service, or by allowing the
third-party application to obtain access on its own behalf. This
specification replaces and obsoletes the OAuth 1.0 protocol described
in RFC 5849.

Disclaimer: I work at Approov.

Why is it safe to put secret keys into iOS binaries

Embedding API keys in an app is not secure and generally not a good practice but does require a substantial work factor to obtain them, it is not trivial. There is no tool to decrypt the executable other than the OS for execution.

RE: "anyone with a jailbroken phone can see the unencrypted executable." is not really true. Just jailbreaking will not decrypt the app binary, it is only decrypted as the binary is loaded in RAM to execute and the key will not be available, it is decrypted in hardware in the DMA path. One needs to add debugging tools and catch the binary after it is loaded into memory for execution.

You need to determine who the attacker is, how much skill and time the attacker will spend and the cost to you.

There is no 100% secure solution, only increasing the work factor.
An alternative is to obtain the API keys on first run at login to a server and then move them to the Keychain. But this is also just an increase in work factor because as above the executable can be examined at run time when it is sent to the service.

As long as the key has to be in the app memory during any part of execution it is vulnerable.

Putting the API keys in the source may meet the security needs.

Safe way to store secretAccessKey on iOS application

The best way to do this is not to give out normal secret access keys at all.

First create an IAM user that has access to only what is needed, so that even if someone does get their hands on the credentials they can only access what you want them too (e.g. get files from a specific S3 bucket, but not modify them)

When the iOS app needs to access the S3 files it connects to a web server you control. That web server users STS to generate a set of credentials that will expire after the desired amount of time. These look like normal aws credentials (access key, secret, session id) but will eventually expire.

Amazon provide some reference implementations of these token vending machines and has an article discussing the setup in more detail.

iOS keychain and encryption keys, how to keep safe until stored

In 3 words: SSL web service



Related Topics



Leave a reply



Submit