tags:

views:

794

answers:

5

Until iPhone 3.0 is available, I need to send an email with what my iPhone app has generated (an image) and to where the user has chosen.

Two solutions, the skpsmtpmessage library, which is not all there and still buggy; or write my own server to forward the emails. The latter is no problem for me, but the question is how can I be sure that the message is from my iPhone app, and not something else?

I can imagine using SSL, but I still wonder about someone on a jailbroken iPhone taking my app apart and then using the faked connection to run spam through it.

My first thought is to make the server only accept data with an exact set of features (such as exactly 1 jpg image, certain exact JSON data) and reject everything else. It could still be DOSsed of course.

Does this make sense? Has anyone done something similar?

EDIT: I won't be sending an email to my server, just JSON and the server will generate the actual email.

+2  A: 

Making it as exact as possible will definitely lower spam. If you make it do something like http POST to the webserver, then let the webserver generate the message, you'll make it harder to spam. (more likely to require a custom setup on the spammer's part)

Some sort of registration system is your best bet, it's far harder to spam if you need to register first, and you can disable accounts that cause problems far more easily.

You're not going to be able to prevent DDOS from the application side, so I wouldn't worry about it too much, just make sure it's not too easy to make the application send a ton of data or perform complex processing.

Eric
making things more difficult is not the same thing as preventing. security by obscurity or effort is not security.
fuzzy lollipop
A: 

Add an extra email header that contains some sort of key. Only accept emails that have the header set with the correct key. That would prevent random people from hijacking the email server, but might not deter someone who has taken your app apart and discovered the key.

To make it more difficult than simply finding your key, you could set keys on a per session basis. Every time the app loads it requests a key from the email server and then uses that key in all email headers sent during that session. That way you could implement behavior tracking and ban malicious users and bots (for example, you could ban any user that sends emails faster than humanly probable).

vamin
making things more difficult is not the same thing as preventing. security by obscurity or effort is not security.
fuzzy lollipop
A: 

If possible, make the interface as useless as possible to spammers. If you're generating an e-mail dump of a series of objects, for example, convert the objects to XML and send those in rather than sending the text of the eventual e-mail. Spammers are looking for the weakest link and will move on if they have to put a lot of effort into using your service.

Brent Royal-Gordon
A: 

What's wrong with skpsmtpmessage?

Elliot
+2  A: 

I'm doing a similar thing on an app I'm working on. You can use a combination of public key encryption, SSL, and the local phone keychain.

  • First of all, all communications between iPhone and server have to be encrypted. This is pretty straightforward if you use HTTP POST requests and SSL. It also thwarts packet sniffers.

  • When your app comes up it looks inside the local keychain for a public RSA key for the server and a stored hash value. If not found it contacts your server with the UDID of the phone which the server uses (along with system time) to generate a hash. It sends back a copy of the hash and its public key to the phone. The server then creates a record in a local database (say, MYSQL) with the UDID and the hash it sent back so it can use it for verification later.

  • The app on the iPhone saves the hash and the server's public key in its local secure keychain. This is all handshake stuff behind the scenes, i.e. no user interaction involved. This is only done the first time the app is run.

  • From then on, every time you want to send an email your app formats your message (the image+JSON part), tacks on its own UDID and the hash value it got from the server, then uses the server public key it has in the keychain and RSA encrypts the whole mess. It adds this to the body of an HTTP POST to the server and sends it (via SSL).

  • The server gets the message, uses its private RSA key to decrypt the message, parses it, looks up the phone UDID in its database and compares the hash values received to the one it saved from that first run to make sure it's a handset with which it has already done a handshake. If verified, it takes the user data and formats it as an SMTP mail message and sends it on its way. It then replies back to the phone with the status.

  • This establishes a two way handshake between phone and server. No user-level accounts were created and it's all behind the scenes. The only information you're saving on the server is the UDID of the phone anonymously so there shouldn't be any privacy issues. The communication is secure (SSL), the server only accepts requests from phones that have gone through the handshake, stored the calculated hash, and to top it off, the whole packet is encrypted through public key encryption.

  • If you want to keep things interesting, every once in a while you can send back a new calculated hash with your status results and have the phone replace the one in the keychain. That way, even if after all this someone cracks your scheme, they'll have to keep up with changes over time.

  • If the user deletes your app and reinstalls it or moves to a new phone you just do the handshake again. The cost is an extra database record on the server. If this is an issue you can also save the 'last transaction' date with the record on the server then expire idle records every N months and force the phone to go through a fresh handshake (instead of considering it an error message). On second thought, you may want to do this anyway. The cost is a short delay every once in a while as the phone goes through the handshake sequence again.

  • To make it doubly interesting, the server that does that first handshake can be a different server than the one that actually does the work later on. The handshake server also sends back the URL endpoint of where subsequent requests should go and the iphone stores that in the keychain too. So even if your app gets decompiled, all they will get is the URL of the handshake end-point. Since most of the data is stored at runtime in the keychain, static analysis of your code from a jailbroken phone will yield nothing of much value.

  • Also for the sake of performance you may want to consider queuing the request on the server as soon as it's been validated and letting the user get back to what they're doing, then using a cron job to pump out the SMTP messages periodically. The advantage is the user response is better. The disadvantage is that if the email address is bad you have no way to respond back to them unless you get fancy with push notifications. I'd make it a user-preference and let them decide if they want to wait for confirmation.

  • All the technical bits for this already exist on the the iPhone (i.e. no third-party libraries needed) and should be easy to implement on a server with Rails or Django.

Ramin
How are you handling all of the RSA-related stuff? I've had a devil of a time working with the Security.framework.
bbrown