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
Related
Am I correct in thinking that a public REST api, such as a registration endpoint can't authenticate a user. For example our endpoints should only accept requests coming from our mobile applications and future web apps.
I am pretty sure it's not logically possible. I think apple and google offer a way (acting like a ca) for the server to identify a request is coming from a registered device however that changes the API to a private one. As authentication is essentially moved to the app store so only owners of app store accounts can use it.
So keeping it completely public the only way to prevent bots attacking it is to use email confirmation with auto deletion if not confirmed in x amount of time, and IP rate limiting.
A contractor suggested we use a unique secret key hard coded in to each app however, that to me sounds illogical and completely wrong. A secret between the app and server is compromised the second a user downloads the application on their device.
So am I correct about the secret key, are there any other ways to secure the endpoint from bots? The only other thing I can think of is using a captcha.
There are 2 separate things here.
Securing Public REST APIs
You are correct that a secret, even an asymmetric one, would be compromised if the attacker downloads and reverse-engineers the application. Attackers can use debuggers, Chrome developer tools, and tools like Wireshark to reverse engineer and find the secret.
In general, an attacker can mimic the behavior of the app or user, i.e. same the same requests in very similar patterns.
The approach to this in today's industry is to filter out as many of those attackers as possible using tools like Web Application Firewalls, and increasingly, Bot Management solutions, which work for web, mobile, and APIs.
The better the tool, the more work the attacker has to do, ergo fewer are attackers willing to do it, ergo smaller chance of being attacked.
Secure Authentication
Authentication is a specific case of the above, however this problem is currently (one of) the biggest problem faced by web applications.
The main solutions employed today is are bot filtering techniques e.g. CAPTCHA (which resourceful attackers can overcome), and Multi-Factor Authentication.
It's quite uncommon these days to be able to register without email, however services such as 10 Minute Mail can be used to overcome this. It's actually not very difficult to set up your own mail server as well.
Login is more difficult because you can't expect people to go through email, and even other MFA methods get quite annoying. You'd be OK with MFA for your bank account, but not with MFA to your Domino's Pizza account.
Because of that, the latest fad in web attacks is Account Takeover.
All those security vendors which offer WAF and bot management also try to protect APIs such as registration & login, with various degrees of success. There are even dedicated products are starting to emerge.
We intend to develop rest based api. I explored the topic but it seems, you can secure api when your client is an app (So there are many ways, public key - private key etc). What about websites / mobile website, if we are accessing rest based api in website which do not use any login for accessing contents ( login would be optional ) then how could we restrict other people from accessing rest based api ?
Does it make sense using Oauth2.0 ? I don't have clear idea of that.
More clear question could be ,How can we secure get or post request exposed over web for the website which doesn't use any login ?
If it's simple get request or post request , which will return you json data on specific input, now i have mobile website , who will access those data using get request or post request to fetch data. Well, some else can also access it , problem is i am not using Login, user can access data directly. But how can we restrict other people from accessing that data.
What do you think is the difference between securing a website that is not using REST vs one that is using REST API?
OAuth provides authorisation capabilities for your site, in a REST architecture this means a user of the mobile application will have to provide their credentials before being allowed to access the resource. The application can then decide on if that user has access to the requested resource. However you've said your website doesn't need use authorisation.
You can use certificates however good luck managing the certificate for each client. My take on it is for your explanation you don't need to secure your website because you will never be able to manage a trust relationship between the client and the server. There are some options though:
You build your own client application that you ship out to people which can verify itself with the server using a packaged certificate with the client. E.g. iOS has this kind of feature if you build for that device.
You provide a capability to download a certificate that is 'installed' in the browser and used when communicating to your REST API
Use something like a handshaking protocol so when a client wants to make the first request it says; 'hi I'm a client can we chat?' And the server responds with 'yes for the next X minutes we can however make sure you send me this key everytime you tell me something YYYYYY' (you can use something like SecureUDID or equivalent for other devices than iOS).
There are probably others but you get the basic idea. Again in my opinion if your resource doesn't need authorisation then you don't need to secure that REST API. Can I ask what kind of data are you exposing via this REST API or functionality your providing? That might help provide a better answer.
You want authorization: only some agents (mobile clients) and/or users should be allowed to access those APIs.
To solve that problem, you need identification: a way for the server to tell who is who (or what), so the right decision can be made.
There are many different way to provide some form of identification, depending how much you care about security.
The simplest is a user agent string, specific to your mobile clients. But it can be faked easily. Slightly harder to fake are client based 'secrets' - embed some kind of secret or key in your mobile client code. You can make it really complicated and secret, but as ramsinb pointed out, you can't get security this way as it would require you to be able to guarantee that the secret you're shipping with the client (wether it's code, algorithm or any other fancy construct) can't be compromised or reverse engineered. Not happening when you don't control the client.
From there, 3 choices:
Security isn't really required, don't bother
Security isn't really required, but you still want to limit access to your API to either legit users/agents or people ready to invest some time hacking your protection - go with a specific user agent or a client embedded secret - don't invest much into it as it won't block people who really want access to get it anyway
Security IS required - and then I don't think there is a way around authentication, wether it's login/password, user specific (device specific?) keys, OpenID, etc... No matter what, you'll have to add to the user burden to some extent, although you can limit that burden by allowing authentication to persist (cookies, storage....)
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.
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.
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