In the application I'm working on, I'm generating a username and password and storing them in [NSUserDefaults standardUserDefaults]. I know there's some system-wide information you can retrieve from there; does that mean all the applications on the phone have access to everything in there? I'm currently prefixing the keys I'm using in there with some strings of characters related to my application name to avoid conflicting with other applications, but is this necessary? And if so, is there a better way to avoid such collisions?
You should also be storing usernames and passwords inside of the keychain and not in user defaults. Storing them in user defaults open them up to snooping when backing up the data to their Mac.
No. NSUserDefaults are not system wide. Name them whatever you like, you'll be fine. :)
NSUserDefaults uses the abstract concept of "search paths" to look for defaults values. Unless you customize it, the standard user defaults object will look in three places; the launch arguments, your application's preferences, and the system preferences (for example global localization options). You can also manually add identifiers for other search paths, if you wanted to share the same preferences between more than one application (I haven't tried this with the iPhone, so I'm not sure if it's available on Cocoa Touch or if you can only do this on OS X).
You could potentially have a conflict with one of the systemwide preferences, but since your application's search path is searched first it's never an issue.
Related
I have a MacOS app coded in swift, and when someone right clicks > show package contents there is a file that reveals some information I do not want the user to see. Is it at all possible to hide that file?
There's no way to secure data on the client (mac) side. If your program can read something, so can a hacker. You can do 3 things about it:
Make it obfuscated enough to make it annoying to deal with, hoping that bad actors would get discouraged.
Make the reward of reading the sensitive data lower, so there's less incentive to do so
Make the sensitive data be black boxed by a server you control and have secured, and have all the sensitive operations be out-sourced to computation on that secure server.
No, you can't hide files in a meaningful way.
If you name the file starting with a dot (".") they are not shown in the Finder by default, but that's very easy to get around.
Better to encrypt the file and decrypt it in your app. That way nosy users can see the file but can't make any sense out of the contents.
I need to code in authentication information for specific parts of my website into my app. Is it at all possible for the app to be "decompiled" and the username and password exposed?
NSURL *url = [NSURL URLWithString:#"https://predefinedUsername:predefinedPassword#www.website.com"];
Yes, it is possible. Assume that if you have anything compiled into your app, it can [and will] be discovered by someone somewhere. Even if it isn't possible today, you are creating a frozen record of such information that will be vulnerable to any future attacks, known or unknown.
You really need the user to perform some task that authenticates them. There are a million and one ways to do that, and for every one of those, a million and two ways to do it wrong. :)
Without knowing more about your specific requirements, it is impossible to really say much more outside of "keep it simple and don't store or send anything in clear-text".
As #Hyperbole said, If you store the username and password in plain text it will be visible in the executable. It is extremely trivial to examine the executable for strings, and it's usually the first thing someone with malicious intent will try.
Right click on any app you've downloaded in iTunes and select show in finder. Make a copy of the app on your desktop and rename the app from AppName.ipa to AppName.zip. Double-click to unzip it, and look inside the folder. Navigate to the folder Payload and then right click on the (probably only) file in there called AppName that looks like an application but has a big circle with a cross through it for the icon. Select show package contents. Scroll through until you find a file called AppName with no extension and a blackish rectangle with the green word "exec" as an icon. Open that file in text edit or another text editor. You'll find that most of this ends up being random symbols and other crap, but you should occasionally see some plain text. The compiler takes string constants and embeds them directly in the app when you compile it in most cases.
You asked about what magazine apps and others do to access content - There are a ton of different ways to do it but off the top of my head, after the server verifies your in-app purchase receipt, the server would record an identifier specific to your iTunes account, saying that you've purchased a specific issue of the magazine. Then your app can request that file from the server, adding the identifier to the request in the process. The server would respond with the file once it looks through the database and determines that you've purchased the content.
Other solutions include signing/hashing a unique key.
Your example would expose the username and password without the need to decompile as you send it via plain text in a URL request. Anyone with a sniffer or MITM service yould snatch it out of the air. A better approach would be to make use of SSL via the http*s* protocol. You could go a step further and either prompt at runtime for the credentials and/or store an encrypted version within the app.
This is very bad because it is trivially easy to recover these credentials just by running 'strings' against the app binary without needing to decompile it.
Can't you pop up a dialogue box asking the user to enter the credentials when they first start the app ? Alternatively you could store them encrypted in a file and then ask the user for an alternative credential e.g. Passcode that derives the key but even this will not survive a determined attack unless the Passcode is long.
I'm trying to implement a backup of my application's data and user preferences (stored in NSUserDefaults) as email attachments with option to restore them at a later date.
I've got the process working fine for my application data file simply by attaching the contents of the file to the email, but can't work out how to do the equivalent for the user preferences. The Root.plist in the Settings bundle contains only the template for the settings interface and none of the current settings.
Reading the settings into my own plist and saving that to the documents directory is an option but seems inelegant and overly complicated. Is there a better way?
I wouldn't go looking for the plist that stores NSUserDefaults, because it's not directly exposed by the API, and hence is an implementation detail that could be changed at any time.
Instead,
[[NSUserDefaults standardUserDefaults] dictionaryRepresentation]
will give you an NSDictionary containing all the key-value pairs that your app has stored.
See this tutorial,
http://iphonebyradix.blogspot.in/2011/03/read-and-write-data-from-plist-file.html
To read user defaults , use this method
-(id)getFromNSUserDefaults:(NSString*)pForKey
{
id pReturnObject;
NSUserDefaults *defaults =[NSUserDefaults standardUserDefaults];
pReturnObject = [defaults valueForKey:pForKey];
return pReturnObject;
}
Reading the settings into my own plist and saving that to the documents directory is an option but seems inelegant and overly complicated. Is there a better way?
Given that there is no official API (that I know of) that directly supports what you want, I find it quite elegant and not very complicated to write a few lines of code that create your own .plist file. See yuji's answer for a starting point: Just one line and you already have a dictionary with all the settings that you want. How much more elegant can it get? :-)
It may not be the answer you would have liked to hear, but my advice is: Don't try to fight the system, you usually lose in the long run.
Recently i've asked about the security implications of storing sensitive info in the xml string resources in Android: the answer? Heavy security implications, is really easy to get the contents of every xml file with a simple command line tool, so it is almost mandatory to have important info encrypted.
Now, how is it like in iOS? How secure it is to have a certain data in a plist or a .strings localizable file, in plain text, non encrypted?
Still not very secure.
There is nothing stopping a user from unzipping an application stored on their computer in iTunes and viewing the contents. Its very easy to do, even without a jail broken phone. Any strings resources, plist files etc will be immediately accessible.
Even hard coded string literals are visible in the compiled binary when one views it with the strings utility. And going a set further, using the nm utility one can see all your applications symbols, such as method names, constants, etc.
I would recommend against storing anything that could be considered sensitive in plain text.
You can access any file on a jailbroken iPhone, so you'll need to encrypt sensitive data.
If your app ships with a .plist file, then the end user can unzip the .ipa app file and see the .plist file and do whatever they want with it.
The exact same problems, a plist is a very common file for Mac OSX and iOS and it is just a XML file. Secure your sensitive data on ALL platforms!
I would like to add that apple does provide a way to securely store sensitive information in the Keychain.
I'm currently in the process of adapting an existing iOS app into what will be a family of very similar apps (each app instance will probably map to a different country/region).
I'm planning on having a different build target for each of these instances, and the only differences between them should be:
Images (probably just the splashscreen and icons)
Localizations
String variables: base URL for remote services, application ID, support e-mails, etc (possibly half a dozen of such variables)
The code itself should be the same on all apps.
What I'd like to know is what you consider to be best practices for managing a family of applications like this.
Regarding images and localizations (or resources in general), it should simply be a matter of adding/removing the appropriate files from the target (and I guess I can even use the same name for images, in different directories).
The main thing I'm not sure about are the other configuration variables.
I've heard / thought of a few options:
Using preprocessor macros and a main configuration header file with the different URLs, IDs, etc
Loading them from a plist (or similar configuration file) whenever the application launches, and having one such file per target
Creating an empty .sqlite file (this app already uses Core Data) and populating it with the default configuration variables, and having one such file per target
I think the first option is the fastest to get out of hand once I have a few instances of this app, plus I have to recompile every time I change one of these settings.
The third option I'm also not sure about, because I'll be adding entities to my database which don't feel like they belong there, plus it kind of feels like overkill for what will probably be 5-10 settings. I'm also not sure about how to add new settings on updates.
So I'm leaning more towards the second option.
Thoughts? Any alternatives to these?
UPDATE #1:
Regarding the second option, there is also a drawback that those strings (ids, URLs, etc) will be slightly more exposed (i.e. if someone was to open the app and look through the plist) than if they were in the source code. Not that this is that big of a problem, but it's just something to consider.
Update #2:
How about using the app's info.plist directly and storing it there? (thus having an info.plist for each target configuration) Even though originally I was thinking of having a separate plist, and having a "configuration singleton" which would load everything from there on startup, I think it may be simpler to simply have it in the info.plist and then reading it via [[[NSBundle mainBundle] infoDictionary] objectForKey:#"com.example.mykey1"].
I would take the preprocessor option. You can put all your preprocessor in one file/method and it will not be too messy. Like oefe said, change the .sqlite is overkill. And with the multiple plist, you will find yourself dragging things around and doing a lot of error prone actions.
However, I would not make a lot of apps. I would just make one app, let the user select his city at launch. You could also add in-app purchases to let the user add more cities when he wants to.
Your app will be easier to maintain : do you want to upload, change description and screenshots for 10+ apps at each update? I find this painful to do with 1 app...
You will not spam the AppStore : having 10+ more apps in the AppStore with the exact same purpose is ridiculous... That's exactly why Apple made in-app purchases, to avoid that situation.
You will have to find different icon for each of your city : your icon is one of the most important aspect when selling your app on the AppStore. You want it to be as polished as possible. Apple won't allow multiple apps to have the same icon and differentiate icon by putting a label on it is not a good option.
I ended up going for the plist, but instead of creating a new one I used the info.plist file for this, thus no need for extra files per target, as I already needed to have a separate info.plist for each one. I simply load them directly from the bundle with:
[[[NSBundle mainBundle] infoDictionary] objectForKey:#"com.example.mykey1"]
I also used preprocessor (with flags set on the target settings) for a couple of things, but that was mostly for when I wanted to disable/remove completely some parts of the app (e.g. to make sure I got everything I commented out enumeration values and even includes in a couple of places).
I think it's relatively clean and I can easily replicate this for future builds without too much of a mess.
Given that the variation is per country/region, and these variables are strings, why don't you simply treat them as localizable strings, thus reducing the problem to one already solved?
Otherwise, I would go for the plist. Sqlite seems to be an overkill, and is not source-control friendly. And conditional compilation will get messy fast.