We have an iOS app which interacts with various webservices at the backend. The backend however wants to validate that the request coming to it is from our valid iOS app and not from a replay attack or a "man in the middle" attack. We are eventually going to have all our calls changed to https. However, is there any way the backend can validate the request is coming from our legitimate app? We were thinking of using cryptographic nonce with every request, but it would still be prone to "man in the middle" attack. Is there any certificate exchange that can be used between the iOS app and the server?
TLS and SSL support client authentication using certificates. NSStream might support client side authentication, but I have not been able to find a way to do it without dropping down to using OpenSSL for the actual implementation.
Addition:
ASIHTTPRequest supports client certificates since version 1.8, so no fuss in implementing it.
what about using a private/public key scheme so that the iOS app can sign every request it sends?
if private/public key scheme may sound scary, the same idea of "signing" your requests can be easily implemented by hashing your crypto nonce by using sha1, sha2 or other cryptographic hashing algorithms. this would be pretty easy to implement (implementation are readily available), fast, and would ensure a higher security level.
I would suggest to use OAuth. It well known and understood and pretty much secure, and in the case that someone gets your token, you can issue a new one with an app update and revoke the old one.
This is a general http problem, not just an iOS issue. In fact, it's the very problem https is designed to solve, or at least mitigate. You can sign the request, use HMAC to authenticate the message, use digest authentication, and so on, but as long as you're using http, a man-in-the-middle attack cannot be easily detected. Spend your time moving to https as quickly as you can instead.
This problem is impossible to solve absolutely. Anything you put into your scheme can be ultimately broken by jailbreaking the phone and running the client in a debugger. Of course, that doesn't mean you can't make it more difficult to spoof your client using client certificates and whatnot, and you should. But if for example the security of financial transactions depend on your app not being spoofable, that would be bad...
Related
A client asked me to do a back-end server for its iPhone application and want only users who bought the application to be able to call the server.
The problem is that he doesn't want to add a login system to the application, so that it seems to me there is no completely safe way to prevent someone without his application calls the server.
In any case, even if it can not be completely prevented, it would be sufficient to make it difficult to access servers without the application.
What is the best way to achieve this? Again, I do not need to fully protect the connection, there is no transit of sensitive information, I just want to make things a little more complicated for people who want to take advantage of server without paying the application.
The idea that seems most simple is to encrypt the data with a key stored within the client and known to the server, so that the message can be decrypted only decompiling the code and finding the key (of course instead of a key you could put a list of keys, which change every 6/12/24 hours).
Could this be a reasonable solution?
This will never be possible. Welcome to the nature of the client-server architecture. You can never trust the client. Just make sure the functionality you are exposing is safe.
well if its a paid app you could release the app for free with all the functionally locked down until a user does a in app purchase and then you could verify the receipt on your server therefore proving that the device is a iOS Device?
sharing a key between the client and the server seems to be a good way to go. But instead of depending on the stored keys only, try combining them with a Unique identifier, such as UUID and send it to server both with the combined key, and the UUID itself.
At that point users UUID will be his identifier (username) and the combined key will be his token (password). And this will be a login-like mechanism.
An SSL connection is not enought to prevent other people from getting the URL for the requests? Or even better using an SSL connection with a basic auth?
I want to encrypt some json from a server and then decrypt it on the iphone/ipad. What are your thoughts on this? What is the best approach to this? Should I scrap this idea and just go via SSL?
Save yourself a lot of trouble and just use HTTPS for all server communications.
As stated above one way is to do everything over https.
An alternative I can think of is the following:
Generate an symmetrical encryption
key per session/login per client on
the server
Send that key to the client over
https
From there on encrypt all the data
you send to the client with that key
The client can then decrypt the
encrypted data
I don't have enough knowledge about https. I often read that is heavy on the resources of the system, but since I have not made or read some good benchmarks I can't give you a rigorous argument for or against it.
The implementation I proposed require a little bit more coding, but you can tailor to your encryption needs.
I think ultimately your decision should be made based on your usage scenario, if you sent very little data, not often to a few client application, you can't go wrong with https. If your expected encrypted traffic is high, the alternative solution might make sense.
I have an iphone app that retrieves and send data to a server that uses python.
What measures could i take in order to prevent security risks?
I an not handling extremely sensitive data but i wouldn't want people sniffing the contents.
Is using SSL enough to prevent most risks?
Thanks
SSL should be sufficient. It's also a good idea to store the user's password (if you need one to login) inside the Keychain. Btw, don't send anything to the server in a QueryString, always do it with a post, otherwise the SSL won't do much to help you.
If you don't have super-sensitive data, you can also use HMAC messages in order to query your server. I've done this with several projects before.
The message sent to the server may be a little more heavy-weight but is a viable option if you don't want to go with getting a SSL certificate.
I'm building a client/server iPhone game, where I would like to keep third-party clients from accessing the server. This is for two reasons: first, my revenue model is to sell the client and give away the service, and second I want to avoid the proliferation of clients that facilitate cheating.
I'm writing the first version of the server in rails, but I'm considering moving to erlang at some point.
I'm considering two approaches:
Generate a "username" (say, a GUID) and hash it (SHA256 or MD5) with a secret shipped with the app, and use the result as the "password". When the client connects with the server, both are sent via HTTP Basic Auth over https. The server hashes the username with the same secret and makes sure that they match.
Ship a client certificate with the iPhone app. The server is configured to require the client certificate to be present.
The first approach has the advantage of being simple, low overhead, and it may be easier to obfuscate the secret in the app.
The second approach is well tested and proven, but might be higher overhead. However, my knowledge of client certificates is at the "read about it in the Delta Airlines in-flight magazine" level. How much bandwidth and processing overhead would this incur? The actual data transferred per request is on the order of a kilobyte.
No way is perfect--but a challenge/response is better than a key.
A certificate SHOULD use challenge/response. You send a random string, it encrypts it using the certificate's private key, then you get it back and decrypt it with the public key.
Depending on how well supported the stuff is on the iPhone, implementing the thing will be between trivial and challenging.
A nice middle-road I use is xor. It's slightly more secure than a password, trivial to implement and takes at least an hour or two of dedication to hack.
Your app ships with a number built in (key).
When an app connects to you, you generate a random number (with the same number of bits as the key) and send it to the phone
The app gets the number, xor's it with the key and sends the result back.
On the server you xor the returned result with the key which should result in your original random number.
This is only slightly hacker resistant, but you can employ other techniques to make it better like changing the key each time you update your software, hiding the random number with some other random number, etc. There are a lot of tricks to hiding this, but eventually hackers will find it. Changing the methodology with each update might help.
Anyway, xor is a hack but it works for cases where sending a password is just a little to hackable.
The difference between xor and public key is that xor is EASILY reversible by just monitoring a successful conversation, public key is (theoretically) not reversible without significant resources and time.
Who is your adversary here? Both methods fail to prevent cracked copies of the application from connecting to the server. I think that's the most common problem with iPhone game (or general) development for paid apps.
However, this may protect the server from other non-iPhone clients, as it deters programmers from reverse engineering the network packet interfaces between the iPhone and the server.
Have your game users authenticate with their account through OAuth, to authorize them to make game state changes on your server.
If you can't manage to authenticate users, you'd need to authenticate your game application instance somehow. Having authentication credentials embedded in the binary would be a bad idea as application piracy is prevalent and would render your method highly insecure. My SO question on how to limit Apple iPhone application piracy might be of use to you in other ways.
I'm writing an iPhone application that needs to send small bits of information (two strings of under 128 characters each, at a time, and this doesn't happen too frequently) to a server when users interact with it. I would like this information to remain confidential, so I'm thinking of some sort of encryption or secure connection would be necessary.
My question is about the server side of things. The server the iPhone app has to communicate with is written in django and is running on lighttpd. What is the most appropriate way (or what is a standard way) of doing this. I was thinking https, which I know on the iPhone I can use ASIHTTPRequest to do a POST request, but I don't know what it requires on the server side. Do I need a certificate? How does the data get encrypted/secured? Are there any django modules to help with this? Do I have to do something to configure lighttpd?
Would something like xml-rpc or json-rpc be simpler? Is it possible to secure such communication? At what level would that occur?
Any help would be much appreciated.
Using xml-rpc or json-rpc are only means to encapsulate your data into a form that is easy to transport. Your iPhone app can transform the Objective C data using one of those formats and your Django server app can transform the data back into Python objects.
Neither of these have anything to do with security.
Creating an HTTPS (SSL) connection encrypts all communication between the client (iPhone) and the server (Django). You will need to get a certificate for the server side. This indicates to the client that the server is who it claims to be. Your next line of research down this path should be about how to configure lighttpd to handle SSL traffic. Once lighttpd negotiates the SSL communication, your Django app will operate as it does for non-secured traffic.
This is your best choice.
If, for whatever reason, you don't want to use SSL, then you could find strong encryption libraries for both ends of the communication. The iPhone app could encrypt the data, send it over an HTTP connection and the Django app could decrypt it. For example, the pycrypto Python library implements strong encryption ciphers such as AES and Blowfish. You might be able to find an implementation of one of these ciphers written in Objective C.
Did you notice that this is getting increasingly complex?
Go with SSL. It's the way security is done for HTTP-based communication.
Hmm it looks like this might be what you're after, have you seen it?
Setting up SSL for Lighttpd/Django
If I read that right, that setup allows your server to answer https and http requests (?)
Then if your whole app isn't going to be https there's this SSL Middleware to help configure some paths as ssl and some not.
If you use https (SSL) on the server side it shouldn't matter if you use XML-RPC or JSON-RPC. All the data you transfer will be encrypted and secure.
I can only speak from our Rails application and nginx. I bought a SSL certificate from GoDaddy (very cheap) and nginx is setup to encrypt the content (Rails is not doing this itself) on the fly when it sends it out. On the iPhone ASIHTTPRequest will be responsible to decrypt the data. All other layers shouldn't be concerned about the encryption, you can send anything you want.
You might also be able to use a self-signed certificate. We decided to use GoDaddy as we also use the SSL certificate for regular browsers, and those show a warning message to the user if they encounter a self-signed certificate, which obviously scares people away.