I'm developing an iPhone app that lets users upload photos to a Google App Engine backend written in Python.
Data is transferred between the device and server via HTTP POST and GET. What is the simplest, most secure way to ensure only iPhones with my app can get data? Also, I don't want the user to enter in credentials, it should be invisible to her.
I could embed a key in the device and send that with every request which the server would check against. But a malicious user could potentially decompile the app and obtain the key. Any suggestions?
With your requirement that the user not enter any form of password, your options are severely limited. As you note, any shared secret key in the app can be pulled out by someone via binary extraction etc. -- in effect, you can't stop a really dedicated cracker finding out the secret and then just submitting that to the server.
There are approaches that are not watertight, but which might make it harder for wholesale abuse of your service. One example might be to release updates for your app every month (or two weeks, or whatever) that contain a new shared secret. Then obviously your web service has to expect the new shared secret, as well as accepting the exising secret, for each time period.
If your data is very sensitive, you might want to stop eavesdropping by using HTTPS; but as Nick says, if you use HTTPS for anything except authentication, you have extra hoops to jump through at App submission time.
Whenever you have a key stored on a device or in software that is accessible by someone it is subject to attack. iOS's keychain is generally a helpful way to store things you want to secure. However, it is still subject to attack. As with all security you need come up with a model that is appropriate for your application.
Also note that there are encryption export restrictions that you should familiarize yourself with if you be intending to use encryption for more than authorization.
Related
I'm building an app with Phonegap. It simply reads xml feeds to display latest articles uploaded by a school for parents to read.
There will be an option where each user of the app can decide whether they want to receive Push Notifications or not. I have a simple database table where the device's registration i.d. from Google Cloud Console is stored. When the user clicks "yes", the registration i.d. is generated and stored on the server. If they then click "no", it's deleted. I want to secure these call to the server with basic HTTP authentification.
Any documentation I have seen on basic authentification describes the sending of username and passwords. But with my application, there is no username or password as the users do not need to sign up. What do I send to authenticate the client? Would there be a key hard-coded on the client side and sent with each request? Couln't this be easily exposed by unpacking the .apk?
I object to the premise of the question. I actually see this as less a security issue and more a preferences issue. Understanding the distinction makes the development of your feature much easier.
Simply modify your application to allow the user to configure what he or she wants to see in the settings and then store the preferences wherever you want on the client (like local storage). The server can then push as before, but the app should simply refuse to render those pushes that the user doesn't want to see.
If you want to simply disseminate non-sensitive content to the users who want to see it, this is a preferences issue and/or a publish/subscribe issue. But it is not a security issue.
Since you have access to server side, you have the control of the whole process. So, in order to handle that, you may think about something like session cookies that a web server creates in case of normal authentication.
I have done something similar and what I've done is to generate a kind of token server side that is stored in the cookies of the device or the localStorage.
So the process flow should be something like this :
Generate a token and store it on the device (cookies or local storage).
For each request, send this value in a http header
From server side, you may identify the user from that token.
For example : you maintain a table that identifies device/token.
That's it
In addition to what the other answers said you can pass a custom useragent string as part of the requests, and validate it matches what you expect. It's not a sure way to 'secure' requests, but along with a (simple) token system and HTTPS this could be enough for your needs.
I have a web app with a JSONP API I'm using with my iPhone app. How do I secure this so requests from other places won't be able to access my API?
Clarification: My data isn't that important. You don't even have to sign in to view it. I just don't want by my DB to work on queries from other sources.
You have embarked on a very very complicated subject. Prepare yourself for some very long nights of reading various cat and mouse techniques of securing your app. I think your best bet is to put a secret string in the header of each request. Something like this:
Secret-Header: #$F#FQAFDSFE#$%#ADSF())*
Validate that header on the server side and use SSL. Someone could easily respond to this post with "Well that doesn't stop this, this and this" and they will be right. The question is, are you a bank that is worried about someone draining your client's accounts? Or are you just worried about 99.9999% of the population not being willed enough to hijack your junk?
Some people have all kinds of opinions on this, but if your users require authentication to access the web services, just require the username and password to be sent in the header via SSL. They can still hijack your services, but wouldn't be able to see anything that they weren't supposed to anyway. That only works on a user level type of setup though. If it's completely public, you have to consider how unimportant your data is. It may not be as important as you think.
You can embed a private RSA key in the iPhone client and send a signed timestamp with each request.
The server would verify the timestamp against the public key and reject unsigned requests.
The enemy can disassemble the iPhone client and steal the key, and you can't do a thing about it.
(other than a blacklisting arms race)
You can use TLS protocol with client certificate.
http://en.wikipedia.org/wiki/Transport_Layer_Security
The only problem with this solution (not solved today) is that the client certificate is stored in the app binary and can be retro-eenginered.
One traditional way to do this is to take all of the url variables you are requesting, add a 'secret' string, and hash the whole thing and add it as an additional url variable. On your API side, you do the same thing, and if the hash matches what you were given, it's probably coming from your app.
We're looking to use the UDID to authenticate a user against server-side web services for an iOS application. My one concern is that users will try to brute force access to another user's account by making auth attempts using random UDID values. I can work on things such as throttling their requests, however I was curious if there is a way to make a "signed" request.
Meaning, is there a way I can certify that the client with UDID foo was generated and sent from the device that UDID foo belongs to, and not some random user with access to curl and a ruby script to call my service multiple times?
I think what I'm looking for is a signed http request. I'm not sure where to start building out such support on either the client or server though.
Those GUIDs are huge. The chance of guessing one seems extremely remote. I'd guess it would take several millennia to come across one 'randomly'.
You are almost surely at more risk of someone sniffing an existing one or using their access to the user's device to obtain it.
Honestly, given how easy it would be to obtain a user's udid, I'd be surprised if Apple didn't recommend against using it that way.
All it takes is for me to email one of your users with a link to my "cool new free game" and bam I've got the udid.
Or, sitting in a coffee shop, and sniffing WiFi traffic - waiting for some ad-sponsored game to send the udid over the wireless for tracking purposes.
But...
How about Client SSL Certificates?
How to use Client Certificate Authentication in iOS App
Or Signed XML Documents?
http://en.wikipedia.org/wiki/XML_Signature
Honestly, there is only so much you can do in this regard.
You'll never be able to stop a truly determined bad guy from cracking open your .ipa and extracting a client side ssl cert - or whatever other mechanism you have to thwart someone.
I'm just saying - since you are distributing the application (this isn't an in-house application running point-to-point over the internet) there is really no way to truly secure the client (mobile) side code - and thus, no way to truly ensure only authorized clients are making requests to your service.
Ultimately, the burden of security is on your services.
You should give a try to HTTP authentication
Building an iPhone OS application that will allow users to anonymously post information to a web application (in my particular case it will be a Rails based site) ... and I want to ensure that I only accept posts that originate from a specific application running on an iPhone/iTouch.
How is this best accomplished?
(btw, if your answer applies to Android please feel free to post it here as well as I'm curious to know if the techniques are the same or vary).
Thanks
The best way would be to implement a known call and response pattern. Send a value of some sort (integer, string, hash of a timestamp) to the iPhone/iTouch application. Have the application modify this information in a known way and send it back for verification. Then all you have to do is use a different modification algorithm per-platform and that will verify what type of device is being used.
VERY simple example:
Server sends 100 with the response to an iPhone.
iPhone adds 10 to this value and sends back with request.
Server detects the value was increased by 10 and now knows it was from an iPhone.
Then on your Android clients add 20 and on another platform add 30 and so on...
You could also add a hidden field in the form. or in the data being passed up if it is XML or other format
Encrypt or sign something using the public key of a key pair, then decrypt or verify it on the server with the private key. Ultimately, anything that can be sent can be duplicated, be it a spoofed html header or an encrypted block. The app has to know the secret handshake, and anyone with access to it (and sufficient technical skills) can figure out the secret handshake.
I would suggest the following approach.
Build an ssl enabled access to your rails app.
Now create a user account for every plattform you want to use and enable your applications to log in with the correct key. If you use the ssl standard in a correct way there shouldn't be a way to sniff the password and you can use standard components on the rail and the phone side of your app.
You then need to secure the login credentials on your phone with the appropriate technics. Eg. put it in the keychain on the Iphone.
I am looking for some suggestions on how to secure access to a RESTful API which initially be used by an iPhone application, but will have other clients in the future. The data exposed by this API must be kept secure as it may contain health information. All access will be done over HTTPS.
I was thinking that I'd like to require pre-registration of the iphones at setup and then also some type of PIN/Password on each request. So, simply knowing the password without pre-registering the phone/client won't provide access. I was thinking about somehow tying it to the iPhone identifier if that is possible, but not sure it would provide any additional security. The iPhone identifier is just another piece of information and it may not even be that secret.
So, some requirements would be:
Use some type of pin-based solution on the iPhone, but want more security then a simple 4-6 digit pin can provide.
No passwords could be sent in the clear.
Not be subject to reply attacks
Having to pre-exchange some data between client and server when setting up client is OK.
I would think that, if the application contains medical records, you would want to have the user authenticate every time they use the application or, at least, have some way of pushing down a disable message that renders the app useless in the case where it is lost or stolen. The 4-6 character password (pin) would also concern me with respect to HIPAA, if it applies.
You might want to treat it as a standard web app from the server perspective and do session-based authentication and access with a session that times out, perhaps after a long period, and re-authentication on timeout.
You could use SSL with client authentication. If a device gets lost, you can remove the certificate on the server. There are some obstacles though:
It is not entirely clear if/how you can do client authenticated SSL on the iPhone Unfortunately, there is not much documentation about it. Have a look at Certificate, Key, and Trust Services Reference
You have to create a private key for every device
You also have to figure out a secure way to transfer the private key to the device