Sending Apple device token to server and avoid spoofing - ios

I'm not sure if I'm being over cautions; I'm implementing the ios push notifications and there's is a part where I need to send the device token to the server, so that's clear, all I had to do is send a request like this:
www.mysite.com?registerIosToken=asdfgadsfhgakjhsf
So my server can register the token in the db.
But what if someone sends multiple random requests to this url?, how can I detect ignore fake requests?,
I was thinking using the app public certificate, and I can decrypt it in the server with my private key, but if the key is public, everyone can encrypt it...

Related

Upload iOS device token for Push Notification

I would like to know how to manage the iOS device token App & Server Side.
First, I registered my app to receive remote notification. So, I got the device Token.
My questions are :
App Side
When Should I send the token to the server ?
If Many times, how often ? Each log Request ?
I should send the token to the server directly from this method application:didRegisterForRemoteNotificationsWithDeviceToken: or store it, and send it in an other method ?
Server Side
Once I have the token on the server, how can I know if the token is still valid ? Or that I should delete it cause the device token is not available anymore.
App side
It's better to upload it in every api request to track the user devices as he may login in his account from multiple devices , so you should have array of device tokens in server , or only one token if you want to track the last device the user is active with so , store token from didRegisterForRemoteNotificationsWithDeviceToken say in user defaults and upload it for every api request
Server side
The token is still valid if the php script used to send it returns success operation but if not that may also mean .pem file is incorrect

Validating requests in /server url

In iOS MDM /server url will be called for each operation by the device when it is woken by APNS. I have securely encrypted and signed other profiles at the time of enrollment and successfully passed the server url to device. Its working fine but I have few concerns over this server endpoint as follows.
1) Any client or entity who could send similar plist payload can invoke this service. If a 3rd party has access to a device UDID they can compose this xml payload and invoke this service. From the server point of view it will be hard to track this behavior and identify real devices. To identify that in the real scenario will it send and CMS data or related to validate this scenario?
2) Once the device hit this endpoint from server we can generate operation profiles and send back to devices. For the profiles at the enrollment time we could extract the public certificate from CMS data and encrypt from that. But for this server url how do I achieve that? Seems its not getting any cert like that from device side. Just wondering whether to save the public keys we got in earlier stages but since at the enrollment it goes through 2 SCEP calls not sure what to use it. Will those subsequent profiles payload can be encrypted using previous public cert? Right now I do the signing anyway which works fine.
1.) Any client or entity who could send similar plist payload can invoke this service. If a 3rd party has access to a device UDID they can compose this xml payload and invoke this service. From the server point of view it will be hard to track this behavior and identify real devices. To identify that in the real scenario will it send and CMS data or related to validate this scenario?
Yes, Any client who could possess the UDID and Server URl can send a valid Plist to your server acting like the device.
But they cannot sign the plist with the private key in the device(Which is generated during SCEP enrolment). You would be having corresponding Public key for it to validate the signature.
To force the device to send the signature along each request to Server URL, you have to include SignMessage tag in your MDM payload and set it as true. Like this
<key>SignMessage</key>
<true/>
So when you include this tag along with your MDM payload, you would be get the signature of Identity Private key in the Header HTTP_MDM_SIGNATURE.
Then you can validate the signature using your public key.
2.) Just wondering whether to save the public keys we got in earlier stages but since at the enrollment it goes through 2 SCEP calls not sure what to use it.
Yes I mentioned in the previous answer you should save the public certificate which is issued during SCEP phase. Later you will use that public certificate to Validate the signature from Device and Encrypt the profile you are sending.
Regarding 2 SCEP calls, First SCEP call is to generate the certificate and securely transfer the MDM Payload and actual SCEP payload which will be used as Idenitity certificate for MDM.
So you should use the second one for validating the signature and encryption.
One more hint is, you would have mentioned IdentityCertificateUUID in your MDM payload. The Identity Certificate SCEP payload should have same UUID as its PayloadUUID . That SCEP payload's certificate will be used as the identity certificate for MDM.
Ok. The bottom line that you want to authenticate device.
Each device has an identity cert (a cert distributed in PKCS12 or through SCEP).
Each time when a device communicate to the server it does authentication using SSL client certs.
Most of the time there is a reverse proxy sitting upfront of your web server. It could be Apache or Nginx or anything else. This reverse proxy terminates SSL connection and checks client certificate. Usually, they are configured to pass this client certificate as a header to your web application.
This way your web app can get this header, get a certificate out of it and check against your DB whether a device with specific udid (passed to your endpoint) have a certificate (passed to your webapp in the header).
I am not sure which reverse do you use and whether it's configured properly to pass the certificate.

Sending Device Token Safely for APNs

For iOS applications that require push notifications, it must first request the user for permission to do so. After that, a device token is generated and with this, the remote server may communicate to the user through this token.
I have read a similar question here and I do not feel it is enough. The picture below is a trusted certificate, it allows me to view all traffic that happens on this device.
With Fiddler2 as well as CertMaker, I can sniff HTTPS traffic, which means the client can probably know what data they are sending, and to where.
My question is, knowing that SSL is not secure from protecting my clients from seeing what I send to the remote server, should I simply encypt with a secret key found within my application?
Such as encrypt("device_token","secretkey_a0a0a0a") (pretend this is Objective-C)?
Couldn't someone just find that key within my application? I also read this question, and it seems that it would be possible to get back the secret key.
My plan for this goes like this:
Within the iOS application, Generate a random string named activate.
Encrypt (not hash), the token by the random string and a secret key that I only know. (secretkey_a0a0a0)
Send the encrypted string along with the generated randomly generated string (active).
Within serverside, I check if I can decrypt a valid token from using the active and my secret key.
I save the token in my database if it is valid.
This prevents people from random entering tokens yes, however, secretkey_a0a0a0 is a string literal. It's very possible to get this within the application binary itself.
My question is, how do I protect this secret key? The answer can also be, how can I prevent people from sending invalid tokens to my server as well.
I have heard of encryption, but doesn't that only apply to resource files?
How should I approach this?
If you do SSL-Pinning ( AFNetworking has this implemented ) you won't be able to (in a reasonable timeframe) sniff the https traffic between the client and server if you don't have the servers private key.
If your fear is that man in the middle can steal your token and send fake push notifications to users of your application, be sure that this cant happend. Since requests to apple apn servers must be signed with pem file, the main concern should be how to keep certificate file secured, and not apn token. If you want to prevent writing invalid tokens in your database then you should implement some CRC or odd/even bit mechanism.
You might want to check the security section in the Push Notifications Guide, in particular the section titled "Token Generation and Dispersal".
The device token is generated by the device connecting through the Apple's APNS. My guess (they don't say in the docs) is that it's unique for a given app identifier.
The APNS then will probably match those identifiers with the pem certificate you use to communicate with it thus validating that the push notifications are actually originating from your app.
Encrypting the device token seems overkill in this scenario.
To prevent someone maliciously spamming your server with tokens, I would hash the token when a secret key and send both the token and the hash to the server. You can then hash the token again on the server, with your secret key, and check that the request is valid.

github-like authentication for api in rails

I am creating an API that will only be used by specific devices. I'd like to authenticate using a public and private key pair, similarly to the way that github authenticates using SSH.
The scheme I think would work is as follows:
The device will request authorization with it's ID.
The server finds the public key of the device by the provided ID and encrypts a random string. The string is sent to the device.
The device receives the encrypted string and decrypts it with its private key, sending the result back to the server.
The server checks the string to make sure it matches and sets the correct session variables for the device if the check was correct.
All of this is over an SSL connection, so step 3 can't be snooped and used to authenticate again. Some devices will not need this type of authorization, so the SSL connection can't just verify that the public key of the device was generated by the server's certificate authority and close the connection if it was not.
First of all, does this make sense, or is there a better way? And second - is there some gem that already does this in rails? It seems like this would be a somewhat common method of doing things.

iOS creating secure token based communication between application and server

For an ios 5.0 application connecting to a rest webservice, the customer wants to implement a token based security to ensure that the data being sent over the network is not intercepted and altered in any way... Doesn't https over ssl ensure that the data is not intercepted? and I thought that this would be enough. Pls advise
However, The way the client wants it to work is that starting with the first client authentication request the server would return a token id that would be used to send the next request. In the response for this next request another token id would be sent back that needs to be used for the next request and so on. The problem is of concurrency. Eg when the apns token comes back and the app has to send that to the server and if at that time the iOS application is already making a data request to the server, then the tokens to be used will not match. also since the app has to regularly poll the server for new items, then there are more chances of such concurrency issues to occur.. Any ideas what efficient solutions I can put in the app to counter this?
Or if anyone can suggest better ways of implementing security over the network data, as a possible alternative to the above approach.. solutions that would work for an iOS app and is not battery consuming?
Help in this would be greeeeaaatly appreciated! :-)
Ps. Jfyi Am already doing md5 security on the token being sent
Doesn't https over ssl ensure that the data is not intercepted?
It depends on whom you're trying to protect agains. Plain SSL will protect perfectly fine against anyone between the device and the server.
But it will be trivial for the device owner to create a man-in-the-middle against a client that trusts all CA's on the device. All he needs to do is install his own private CA-certificate on the device, issue a fake certificate for your server signed by this CA, and install this certificate on his proxy/MitM device. To avoid this attack you'd need to do certificate pinning in the App.

Resources