What is un-secure about NSUserDefaults, is manual encryption safe? - swift

If I understand correctly: NSUserDefaults is an un-secure place to store sensitive data because some settings file can be hacked and the NSUserDefault values can be changed.
What exactly can be hacked and not hacked? Can the Hacker see my app's Swift Code, or do they only see the list of variables and values stored in NSUserDefaults?
Could I create my own "encryption" in my code (where the NSUserDefault values appear like a bunch of meaningless numbers, and the "key" is inside my code with some convoluted mathematical operation to do)? Is this safe?
Note: I don't intend on encrypting anything serious like usernames or passwords, just Highscores and Bool values for whether or not levels/upgrades are unlocked. I don't want to have to learn KeychainsWrappers if my manual solution is safe.
Side-question (though I haven't reached this step yet): How are in-app purchases handled? is there a Bool value that says whether or not an item was paid for, and where is that Bool stored (is it up to you to decide)?

What exactly can be hacked and not hacked?
Most everything you can do can be hacked.
Can the Hacker see my app's Swift Code, do they only see the list of variables
A sophisticated hacker can see the executable binary but not the Swift source code.
values stored in NSUserDefaults?
It is trivial to see the contents of NSUserDefaults. See iExplorer and other similar apps.
Could I create my own "encryption" in my code
Sure, but should you?
"Schneier's Law": "Anyone, from the most clueless amateur to the best cryptographer, can create an algorithm that he himself can't break."
Is this safe?
No it is not safe. If you want use encryption you need a standard encryption algorithm such as AES but it is not that easy to create a secure scheme. You can use a wrapper library such as RNCryptor. But this creates a new problem: where to safely save the encryption key, see next point.
I don't want to have to learn KeychainsWrappers if my manual solution is safe.
Only if you want to securely wan to to save keys and small amounts of data. Security is hard.
You need to evaluate the level of security you need, this included the level of attacker and the value of the data. Attackers run from curious students to nation states. Data values run from Tic-Tac-Toe high scores to nuclear arms details. You need to determine these first.

NSUserDefaults is just a plist stored in the device filesystem. Its only 'security' is that people have to go into the device filesystem to get to it, which isn't particularly difficult.
According to the apple docs about in app purchases:
After making the product available, your app needs to make a persistent record of the purchase.
source
You can read more in the section about persisting your purchases for more information, but ignore the parts where it says you can use user defaults to do so.
Also I can't ever recommend rolling your own secure storage system if you don't know what you're doing.
The above is assuming you are talking about in app purchases. If you are talking about stuff local to the user, does it really matter if they hack your app? Say you have a system where you have to beat the previous level to unlock the next level. Who really cares if someone edits their defaults to unlock the next level. Its not something they had to pay for so it doesn't affect your revenue stream. In fact, I would argue it's better to allow people who really want to cheat to do so as long as it doesn't affect your revenue or other players.

Related

Application-specific data protection on iOS

I've seen some documentation and videos from WWDC about data protection in iOS5 and it seems very nice since it can encrypt all your application data and keep it protected as long as your device is locked. However, I see 2 main problems with that system-wide data protection mechanism:
1- if somebody manages to steal my iPhone while it is not locked (which is typically what happens on a "steal-and-run" case), it can potentially plug my iPhone into a laptop and access my data unencrypted
2- it forces me to define a system-wide passcode, which seems natural to some users but is still cumbersome to a lot of users. And it seems abusive that I force my users to define a system-level passcode even though my app is the only one where encryption might really require it. And it's even more abusive as a four-digit password is not such a good protection against brute force attacks.
So my question is the following. Is there any simple way to encrypt my data with a passcode specific to my application, so that every time a user launches the app, they have to enter the passcode, but they don't have to define one on the system level? If not, can I at least plug into standard data protection API's with such an application-specific passcode? If not, is it worth it to write my own encryption layer on top of core data to enable such a scenario? Or is it something that might be added to future versions of iOS (in which case I'll probably stick with system-wide passcodes for now and upgrade it later)?
Several data protection api's on other operating systems (e.g. DPAPI on windows) allow developers to provide supplemental entropy for the key derivation process used to protect the data . On those systems, you could easily derive that data from a pin number. Without that pin, then you can't generate the key and read the data.
I looked and couldn't find anything to this effect on iOS, but I am not an objective c programmer so frankly , reading apple's documentation is a pain for me, and I didn't look too hard.
Depending on your use case you may want to enable data protection in your app, but if the user doesn't use a passcode it won't give you much protection. I don't know if enabling that entitlement will force a passcode.
You could take the path to require that the app have a pin code at launch and then use that pin code along with some other data data to generate a key for the common crypto functions.
https://developer.apple.com/reference/security

Protect an sqlite file on IOS

I have some data I’ve spent months collecting, cleaning and structuring. The app I'm building will be able to search the data. So far I'm storing the sqlite file in the users filesystem and not on a remote server because I want the search result to be instant to give users the best experience possible, independently of their connection speed.
But I've just discovered anybody with a jailbroken phone can just "steal" the information store in my sqlite file.
The last thing I want is for someone to get the result of my hard work and publish it on a website which could potentially makes the app useless.
Is there any way to stop this from happening?
Thanks for your help!
What you want is a form of DRM. Ultimately, DRM cannot prevent a dedicated attacker from getting at the underlying data. Anything the user can access can, in theory, be accessed by a malicious application.
You can encrypt the rows of the database and hide the key somewhere in the app, but an intrepid hacker will find it. You can download the whole file on first run and encrypt it with a key unique to that device, but then you have to store the key somewhere or have an algorithm for regenerating it--and a hacker can get at either (even if it's in the keychain.) If you require a network connection and use a key generated from something server-side and client-side... well, an attacker can just spoof the request and get that server-side component anyway.
So it really depends how secure you want to be. If you just want to keep honest people honest, simple encryption is often good enough. If you want to make a bulletproof DRM system... you'd be the first to accomplish it.
You can use Encrypted Core Data to secure your data.
This library actually decrypts your database at runtime. You can leave your PASSCODE in your .m file. (My assumption is that it is difficult to get the hardcoded PASSCODE from the object file)
And as #jonathan put it, if some person is desperate to get your data, they will.
EDIT:
As Zaph mentioned in the comments section, do not try to put password in your code either directly, or by obfuscating them in your code by some logic, as any one who is desperate to get your key could reverse engineer your binary and get it.
Is it possible to reverse-engineer my iPhone application?

Data protection on mobile devices

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.

CoreData SQLite protection

I like to use CoreData and their entity model into my projects.
I need to know that how to store sqllite database into Iphone securely.
As everybody knows when the Iphone broken with jailbreak it have file system navigatable, that mean for me, someone or somebody easly open or copy to another envorinment my sqllite db. How do i protect my db for these issues ?
Thank you
Answer in bold.
If they have jailbroken your iphone and have the will to steal data, they will probably have the ability to decrypt anything you put there; this is especially so if the data is of any value. To use encryption in this scenario your application will have to store the password somehow, unless you expect the user to enter this every time using the iphone keyboard -- which is a big no-no from a usability point of view. I suggest you rely on the access baricades and remote-wipe facility provided by apple.
If your a going to rely on apples 4-numeric pin as a password -- i.e., to balance useability.... well that only has 10,000 combinations.... not very secure.
However.... the simplest and the time-tested approach is to use a reversible encryption block-cypher in block-chained mode to encrypt the content of the sensitive columns, and to retrieve the password from the user every time the application is started.
-- edit : further discussion --
If I was expecting contents to be encrypted in a mobile way, I would expect the user of the contents to have a USB stick with the contents on it and a security hardened laptop/netbook with the something like truecrypt running on it.
I was not aware that a phone can be jail broken without the consent of the user ?
On the iPhone 3GS all data stored on the phone is encrypted.
I don't know what you are storing, but leaving the security to Apple may be OK.
Did you read this?
http://images.apple.com/iphone/business/docs/iPhone_Security_Overview.pdf
If you really only have under 10,000 records, and they are smallish - like say a short string or two in size, then you could just use an NSDictionary / NSArray with 10,000 items in memory at a cost of 10k*.256k = 2.5 MB in memory, which is not much. If the queries will be simple, then you don't need sql at all. Just run through all records on each search.
You could store an NSDictionary as an exncrypted file, password protected, with the user entering the password on each launch.
Are you worried about someone who has stolen the phone getting the information? Or the person who owns the phone getting to the files your app contains?
If it's not the user there are safeguards you can take, like the password presentation every time (hint: users will hate it and your app will get all 1-star reviews).
If it's the user you are worried about, you are insane to think you can protect anything the user has on their own device. You can just apply some simple obsfucation and call it good.

How would you keep secret data secret in an iPhone application?

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.