Currently we are developing a track and trace app for our company. To make this app more secure we would like to to ask the user at first launch for a security code. This security code will most likely be the customer number.
Ones the user sends a request to the server with his trace and trace code the server will check if the security code and the track and trace code are linked.
My question is what would be the best way to store the security code in the app so that the app can ask for it ones a track and trace gets send to the server. We want the user to enter the security code only at first start.
[[NSUserDefaults standardUserDefaults] boolForKey:#"security code"];
would this be an option?
For any secure data you wish to store on the device, I strongly advise you use the Keychain. You can then check for the code's existence within the keychain, and use that if it's available.
See the following documentation below to get you on your feet with the Keychain!
Keychain Concepts https://developer.apple.com/library/ios/#documentation/security/Conceptual/keychainServConcepts/02concepts/concepts.html#//apple_ref/doc/uid/TP30000897-CH204-TP9
How to implement on iOS https://developer.apple.com/library/ios/#documentation/security/Conceptual/keychainServConcepts/iPhoneTasks/iPhoneTasks.html
Reference https://developer.apple.com/library/ios/#documentation/security/Reference/keychainservices/Reference/reference.html#//apple_ref/doc/uid/TP30000898
Sample Project https://developer.apple.com/library/ios/#samplecode/GenericKeychain/Introduction/Intro.html#//apple_ref/doc/uid/DTS40007797
user1805901> This security code will most likely be the customer number.
How guessable is that? You might want to look into a UUID in case of loss. Provide the mapping from UUID to customer number at the server.
WDUK> For any secure data you wish to store on the device, I strongly advise you use the Keychain.
In addition to Keychain, you also have to look at kSecAttrAccessibleWhenUnlocked, kSecAttrAccessibleAfterFirstUnlock, kSecAttrAccessibleAlways, kSecAttrAccessibleWhenUnlockedThisDeviceOnly, kSecAttrAccessibleAfterFirstUnlockThisDeviceOnly, and kSecAttrAccessibleAlwaysThisDeviceOnly.
kSecAttrAccessibleAlways and kSecAttrAccessibleAlwaysThisDeviceOnly are poison, and should not be used since the Keychain can leak the data. See iOS Keychain Weaknesses for details (its gotten better, but its can still be a problem).
*ThisDeviceOnly means the secret is not included on a restore to a different device. Its helpful for some Copy/Paste attacks.
And if you don't want the secret on the cloud, I believe the Keychain attributes need to include com.apple.MobileBackup. See Technical Q&A QA1719 for details.
Jeff
Related
I'm developing an app that's pretty simple, and the important part of it is the content, which consists of lots of info that has been gathered over many years. I want to format it in a nice way to show to the user.
When the user downloads the app and first loads it, it goes to the server to get the whole database into the phone. Then, he can see the important items, and sort/filter through them. To avoid somebody taking my database, I'll use a SSL connection. I know if they want they could use the app to see every piece of content one by one, but there's nothing to do about that.
The thing is: I have the data in the cloud (mine). I can securely download it using an SSL connection (any other ideas to secure the transfer?). When I get it here, I'll save it in a db (Core Data is the obvious choice).
How can I secure the data in the internal database, so if the app is hacked, someone cannot access the db? I would put it in the keychain but it's a rather large db for that and it's not that important. (It's not sensible info, just info I don't want anybody to get massively.)
The other thing I could do is to never store anything in the device and have the user always making calls to the cloud, but I think this would be too time consuming. And just give him the option to save their favorite picks to the device. But that's too time consuming and there is the sync issue.
This is a reference I looked up about a similar issue, without the part I'm asking answered:
How to encrypt iPhone upload and download of info?
Basically, the only choice is to use SqlCipher. Of course, you have to port it to iPhone yourself (unless someone else has posted a port since last I looked). But it's not an insurmountable task.
Of course, even with SqlCipher you have the challenge of storing the key somehow. There's no really secure way to do this -- you have to use some form of "security by obscurity".
Why not just have some private key info stored in the code, and then when you want to download the database just have it query the server with the key? That way you wan't need to worry about SSL or encryption in the downloading part. In regards to storing it I agree with Hot Licks, SqlCipher appears to be the best and only option. However watch out for encryption, as you will have to declare it to apple and get all kinds of export permits (http://stackoverflow.com/questions/2135081/does-my-application-contain-encryption).
Hope this helps,
Jonathan
When thinking about iPhone/iPad applications security, I can notice that there is:
Widely available hacking tools allow filesystem access
Network interception, men in the middle attack
==> data theft threat
and also:
Availability of hacking tools that allow to freely share a paid app with friends/community (seen in Cydia)
Availability of hacking tools that allow to get in app purchases without paying (seen in Cydia, and heard that it doesn't work with any app)
==> Revenue loss threat
So I am wondering #1 what are best practices to get a better security in iOS application?
Also, #2 what are best ways to reduce revenue loss and minimise hacking exposure?
for #1
I've seen some WWDC slides about security
1 2 3 4
+ apple docs
and I can say that between theses best practices there are:
Using APIs Offering Data Protection (like NSFileManager with NSFileProtectionKey attribute)
Using Keychain
Protecting sensitive data with SSL and using certificates
for #2
I think that using a business model based on free application, then in app purchase with Store Receipts verification can be the model with minimum revenue loss.
What are your best practices for security, and best way to minimise app hacking chances?
#1 what are best practices to get a better security in iOS application?
Appropriate data security is highly dependent on the nature of the information. Is it long-lived or short-lived? Is it a general credential that can be used to open other things, or a single piece of data? Is the potential loss privacy, financial, or safety? Determining the appropriate protections requires a specific case and has no general answer. But you ask for best practices and there are several. None of them are perfect or unbreakable. But they are best practice. Here are a few:
Store sensitive information in Keychain
Set Data Protection to NSFileProtectionComplete wherever possible.
Do not store sensitive data you don't actually need, or for longer than you need.
Store application-specific authentication tokens rather than passwords.
Use HTTPS to verify the server you are contacting. Never accept an invalid or untrusted certificate.
When connecting to your own server, validate that the service presents a certificate that you have signed, not just "a trusted certificate."
This is just a smattering of approaches, but they set the basic tone:
Use the built-in APIs to store things. As Apple improves security, you get the benefits for free.
Avoid storing sensitive information at all and minimize the sensitivity of what you do store.
Verify the services you communicate with.
#2 what are best ways to reduce revenue loss and minimise hacking exposure?
This has been discussed many times on SO. This answer includes links to several of the other discussions:
Secure https encryption for iPhone app to webpage
The short answer is: worry about your customers, not your non-customers. Many pirates will never, ever pay you money, so your time and money are better spent helping your actual customers want to pay you, and making it easy for them to do so. Focus on making more money rather than protecting yourself from money that you could never have. Never, ever, tick off a paying customer in your efforts to chastise a non-paying customer. Revenge is a sucker's game and a waste of resources.
There are two great ways to avoid piracy:
Don't publish.
Publish junk no one wants.
There are some basic things you can do that are worth it just, as they say, to keep honest people honest (some are discussed in the various linked discussions). But don't lie awake nights worrying about how to thwart pirates. Lie awake worrying about how to amaze your customers.
And always remember: Apple spends more money than most of us have ever seen in our lives trying to secure the iPhone. Still it's jailbroken. Think about what your budget is going to achieve.
When the attacker gains physical access to the device (e.g. theft), he can do almost anything.
Note that is very easy to read application files.
Stolen device can be jailbroken easily and the attacker gains access even to the protected files.
My advice for storing sensitive data to the device:
don't do it if they can be stored on secure server
use your own encryption, decrypt when user is logged in, delete decrypted file when they logs out or after some time the app is in the background.
every password and encryption key must be stored into the keychain.
Rob Napier mentioned good points. But to make it more secure,
1 what are best practices to get a better security in iOS application?
Store sensitive information in encrypted format in Keychain.
Upon physical access to the device keychain data can be dumped easily.
Set appropriate Data Protection class (NSFileProtectionComplete preferable).
Always use custom encryption along with built in API to store data.
Even if hackers find loopholes in built in API, your app is secure.
Over write temporary stored data before deletion.
Forensic techniques can be used to recover the deleted data.
Use HTTPS and certificate pinning. Never accept untrusted certificates.
Store important plist, sqlite, etc... files in Library/caches folder.
Files stored in the caches folder are not backedup with iTunes.
Always build the app with latest XCode.
Adds support only for latest SSL Ciphers
2 what are best ways to reduce revenue loss and minimise hacking exposure?
It may not be possible to stop the piracy but we can make it tough.
Prevent the app from running on Jailbroken devices (think twice, you may lose valid customers)
Add code that detects the existence of Jailbreak
Prevent the app from attaching to debuggers
Apps downloaded from AppStore are encrypted. Debuggers are used to decrypt and analyze the App. Add code that detects debuggers.
It varies really depending on what you do. As for accessing an API, all you really need to do is hash and/or salt user information and then save the information (if necessary) in the keychain (you could add extra security by encrypting the passwords before pushing them into the keychain. It's best that you don't use NSUserDefaults as the data entered into it is stored in a .txt file on the iPhone filesystem, which as you said, can be accessed by hackers.
Adding more to improve the security of the application
Do not send parameters using HTTP GET instead use HTTP POST.
You can do SSL Pinning to avoid MITM Attacks.
Remove all the logs from the source before moving to production.
Do not hardcode encryption key's in the app itself, it is better to keep them somewhere remote.
When making a request always use the latest SSL version (TLSv1.2).
If your app has WebView's then beware of Link Injection. If you do not expect any URL's other than HTTP in the WebView then check all the redirect URL's with prefix "http" so that the loaded website does not allow other link's to be opened.
You can choose to allow or block Keyboard Extensions since they listen to all your keystrokes.
I'm trying to send data from my application to a webserver.
The catch is that I want to encrypt the sent data and also make sure it comes from my application. (From what I've read so far it's easy to decrypt the data if it's not sent via HTTPS. On the unique application I didn't find anything except the Application ID Apple provides for each application but I don't know how that works).
The data sent are various highscores and achievements that the user can enable. The thing is that the user doesn't have to type in anything but his username and having that associated with the UDID it should be enough.
But how to make sure it's from my application?
Edit:After reading some responses around here I still didn't understand something:
If someone extracts the IPA and reverse engineers it wouldn't he have access to all my .h and .m so he can look up anything in there?
You could generate a client certificate for the iPhone app, and use mutual authentication for your SSL handshake. Then you know that data submitted to the server come from a particular user of the app, and that your app is communicating with the correct server.
Regarding your edited update, yes if someone reverse-engineeres your app they can probably work out how the high-scores are protected. But seriously, how much trouble do you expect most people to go to in order to fake a high score in a game? Are you offering a cash prize or something?
If you are using HTTPS then you can just put an identifier key in your POST to the web server, either as a field or perhaps an HTTP header that identifies your app. The entire connection is encrypted so it will be protected. If you do this you will want to encrypt the key even in your binary and decrypt it as you send it over the connection, that way no one will be able to pull it out with a hex editor.
Another approach if all you want is to know that the data comes from an authentic instance of your application is to use message authentication codes (MAC). I leave deciding how strongly the key needs protecting as an exercise to the reader - you know your security requirements better than I do.
You can use CommonCrypto - part of the iOS SDK since forever - to actually generate the MAC.
I'm storing some healthcare data on a mobile phone and I'd like to know what the best system of encryption is, to keep the data secure. It's basically a bunch of model objects, that I'm serializing and storing using NSKeyedArchiver / the equivalent on Blackberry (the name eludes me for now)
Any tips? I don't want to make up security protocols as I go along, but one of the other threads suggested the following approach.
Generate a public / private key pair
Store the public key
Encrypt the private key with a hash of the user's password.
Use the public key to encrypt the byte stream.
Decrypt the pvt key, keep it in memory, whenever the user logs in, and decrypt the stored data as needed.
Is there a more standard way of doing this?
Thanks,
Teja.
Edit: I appreciate it that you're trying to help me, but the things currently being discussed are business level discussions, on which I have no control of. So rephrasing my question, if you ignore that it's healthcare data, but some confidential data, say a password, how would you go about doing it?
There might be an easier way for secure data storage. With iOS 4.0 apple introduced system provided encryption of application documents. This means that the OS is responsible for doing all the encryption and decyryption in a fairly transparent way.
Applications that work with sensitive user data can now take advantage of the built-in encryption available on some devices to protect that data. When your application designates a particular file as protected, the system stores that file on-disk in an encrypted format. While the device is locked, the contents of the file are inaccessible to both your application and to any potential intruders. However, when the device is unlocked by the user, a decryption key is created to allow your application to access the file.
So only when your app is active, the files can be read back in unencrypted format. But the nice thing is that they are always encrypted on disk. So even if someone jailbreaks the device, or backs it up, the retrieved files are worthless.
This was probably introduced to conform to some specific data security standard that is required. I can't find that anywhere though.
For more info see the iOS 4.0 release notes.
http://en.wikipedia.org/wiki/HIPAA
Make sure you read and understand this!
edit: Sorry, didn't even bother to check to see where the OP is from, but even if they aren't from the USA there are still some good practices to follow in HIPAA.
HIPPA is a business practice and total system level privacy/security regulation. As such, an app can't comply by itself on random hardware for a random user. You need to determine how your app fits into a client health care provider's total regulatory compliance process before you can determine what algorithm might be found to comply with that process.
My best advice would be, don't store sensitive data in the user's mobile phone.
If that is not an option for you, then some kind of public/private key encryption, such as one you described, would be the next best option.
Let's say I need to access a web service from an iPhone app. This web service requires clients to digitally sign HTTP requests in order to prove that the app "knows" a shared secret; a client key. The request signature is stored in a HTTP header and the request is simply sent over HTTP (not HTTPS).
This key must stay secret at all times yet needs to be used by the iPhone app.
So, how would you securely store this key given that you've always been told to never store anything sensitive on the client side?
The average user (99% of users) will happily just use the application. There will be somebody (an enemy?) who wants that secret client key so as to do the service or client key owner harm by way of impersonation. Such a person might jailbreak their phone, get access to the binary, run 'strings' or a hex editor and poke around. Thus, just storing the key in the source code is a terrible idea.
Another idea is storing the key in code not a string literal but in a NSMutableArray that's created from byte literals.
One can use the Keychain but since an iPhone app never has to supply a password to store things in the Keychain, I'm wary that someone with access to the app's sandbox can and will be able to simply look at or trivially decode items therein.
EDIT - so I read this about the Keychain: "In iPhone OS, an application always has access to its own keychain items and does not have access to any other application’s items. The system generates its own password for the keychain, and stores the key on the device in such a way that it is not accessible to any application."
So perhaps this is the best place to store the key.... If so, how do I ship with the key pre-entered into the app's keychain? Is that possible? Else, how could you add the key on first launch without the key being in the source code? Hmm..
EDIT - Filed bug report # 6584858 at http://bugreport.apple.com
Thanks.
The goal is, ultimately, restrict access of the web service to authorized users, right? Very easy if you control the web service (if you don't -- wrap it in a web service which you do control).
1) Create a public/private key pair. The private key goes on the web service server, which is put in a dungeon and guarded by a dragon. The public key goes on the phone. If someone is able to read the public key, this is not a problem.
2) Have each copy of the application generate a unique identifier. How you do this is up to you. For example, you could build it into the executable on download (is this possible for iPhone apps)? You could use the phone's GUID, assuming they have a way of calculating one. You could also redo this per session if you really wanted.
3) Use the public key to encrypt "My unique identifier is $FOO and I approved this message". Submit that with every request to the web service.
4) The web service decrypts each request, bouncing any which don't contain a valid identifier. You can do as much or as little work as you want here: keep a whitelist/blacklist, monitor usage on a per-identifier basis and investigate suspicious behavior, etc.
5) Since the unique identifier now never gets sent over the wire, the only way to compromise it is to have physical access to the phone. If they have physical access to the phone, you lose control of any data anywhere on the phone. Always. Can't be helped. That is why we built the system such that compromising one phone never compromises more than one account.
6) Build business processes to accommodate the need to a) remove access from a user who is abusing it and b) restore access to a user whose phone has been physically compromised (this is going to be very, very infrequent unless the user is the adversary).
The simple answer is that as things stand today it's just not possible to keep secrets on the iPhone. A jailbroken iPhone is just a general-purpose computer that fits in your hand. There's no trusted platform hardware that you can access. The user can spoof anything you can imagine using to uniquely identify a given device. The user can inject code into your process to do things like inspect the keychain. (Search for MobileSubstrate to see what I mean.) Sorry, you're screwed.
One ray of light in this situation is in app purchase receipts. If you sell an item in your app using in app purchase you get a receipt that's crypto signed and can be verified with Apple on demand. Even though you can't keep the receipt secret it can be traced (by Apple, not you) to a specific purchase, which might discourage pirates from sharing them. You can also throttle access to your server on a per-receipt basis to prevent your server resources from being drained by pirates.
UAObfuscatedString could be a solution to your problem. From the docs:
When you write code that has a string constant in it, this string is saved in the binary in clear text. A hacker could potentially discover exploits or change the string to affect your app's behavior. UAObfuscatedString only ever stores single characters in the binary, then combines them at runtime to produce your string. It is highly unlikely that these single letters will be discoverable in the binary as they will be interjected at random places in the compiled code. Thus, they appear to be randomized code to anyone trying to extract strings.
If you can bear to be iPhone OS 3.0-only, you may want to look at push notifications. I can't go into the specifics, but you can deliver a payload to Apple's servers along with the notification itself. When they accept the alert (or if your app is running), then some part of your code is called and the keychain item is stored. At this point, that is the only route to securely storing a secret on an iPhone that I can think of.
I had the same question and spent a lot of time poking around for an answer. The issue is a chicken and egg one: how to pre-poluate the keychain with data needed by your app.
In any case, I found a technique that at least will make it harder for a jailbreaker to uncover the information - they'll at least have to disassemble your code to find out what you did to mask the info:
String Obfuscation (if the link breaks search for "Obfuscate / Encrypt a String (NSString)")
Essentially the string is obfuscated before placed in the app, then you unobfuscate it using code.
Its better than doing nothing.
David
EDIT: I actually used this in an app. I put a base coding string into the info.plist, then did several operations on it in code - rot13, rotate/invert bytes, etc. The final processed string was used to decode the obfuscated string. Now, the three letter agencies could for sure break this - but at a huge cost of many hours decoding the binary.
I was going to say that this is the best technique I've come across, but I just read Kiran's post on UAObfuscatedString (different answer), which is a completely different way to obfuscate. It has the benefit of no strings saved anywhere in the app - each letter is turned into a method call. The selectors will show up as strings, so a hacker can quickly tell that your class used that technique though.
I think that this similar question, and my answer, may be relevant to your case too. In a nutshell, there was some talk of a trusted platform module being present in an iPhone. This would allow your service to trust an iPhone, even in the hands of an attacker. However, it looks like using the keychain is your best bet.
Did you consider/try the Push Notification suggestion, for initially transmitting the secret to the app & keychain? Or end up finding some other method to achieve this?
I'm going have my iphone app upload images to Amazon S3. Instead of putting the AWS credentials in the app, I am going to have the app phone home to my server for the URI and headers to use in the S3 upload request. My server will generate the S3 URI, proper signatures, etc. I can then implement a tighter, more specific security model on my app's webservice than AWS offers by itself and not give away my AWS keys to anyone with a jailbroken iphone.
But there still has to be some trust (credentials or otherwise) given to the app, and that trust can be stolen. All you can ever do is limit the damage done if someone jailbreaks an iphone and steals whatever credentials are in the app. The more powerful those credentials are, the worst things are. Ways to limit the power of credentials include:
avoid global credentials. make them per-user/application
avoid permanent credentials. make them temporary if possible
avoid global permissions. give them only the permissions they need. for instance, write permissions might be broken down into insert, overwrite, delete, write against resource group A or B, etc, and read could be broken into read named resources, read a list of all existing resources, read resource groups A or B, etc.
I would recommend creating a key at run time if possible. This way if the key were to get apprehended during a particular session, once the session ends, the key will be worthless. They could still apprehend the key from memory if they are smart enough, but it wouldn't matter since the key would become invalid after a period of time.
Sounds wonky. Would use HTTPS and maybe an encryption package to handle the key.
I think CommonCrypto is available for iPhone.
EDIT: Still sounds wonky. Why would anyone pass a secret key in an HTTP header? Anyone who traces your network traffic (via a logging wifi router, for instance) would see it.
There are well-established security methods for encrypting message traffic...why not use them rather than invent what is basically a trivially flawed system?
EDIT II: Ah, I see. I would go ahead and use the Keychain...I think it is intended for just these kinds of cases. I missed that you were generating the request using the key. Would still use HTTPS if I could though, since that way you don't risk people deducing your keygeneration scheme via inspection of enough signatures.