iOS network issue. TLS Session cache loophole - ios

I'm facing a security-related issue for my iOS application. I'm using HTTPS for all my network calls and the public certificate used is from Trusted Authority which is bundled in the application to prevent Main in the Middle Attack (ref: Man in the middle attack - Wiki). I'm doing SSL Pinning (verifying the certificate from server in/before every network call) in Android it works perfectly fine, in iOS however there is a TLS Session Cache which cache the certificate validity after first network call.
For first network call the certificate validation part works fine, for 2nd call, cache is used by OS and I'm unable to verify the certificate. My QA team can easily attack and get all the data from the network call for 2nd and consecutive network calls. Here's the reference for TLS Session Cache iOS documentation. Seems like there's no way to clear the cache programmatically ref: AdvancedURLConnections.
Changing query parameter doesn't help, I already tried that. Please provide iOS specific solution. I can't do encryption of my data for business reasons.
EDIT:
I'm using below mentioned method to verify my certificate. For first network call this method is called by the OS, for consecutive calls this method is not being called.
willSendRequestForAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge
My QA team simply does MiTM attack for every network call, they try to use their certificate and if for any network call I don't verify certificate then they can easily read the data. Because of cache I'm unable to verify my certificate.

The answer to this question is that this method will be called again if you switch your network. The response or result of the authentication is persistent for a session and as long as the session is valid, the connection is secured. So just rely on the framework's method and keep your communication secured :)

Related

How to protect JSON API from being accessed by anyone but my iOS client?

I have an iPhone app that uses a Rails server HTTP API. The API is public at this point - no authorisation is required to get the data.
Currently anyone can go to API's URL and download the data.
http://server.com/mydata
The data is not very sensitive. But I still want to prevent people from easily getting it. What are the ways of doing that? I do not want iOS app users to log in either.
Current solution I have
iPhone app adds a secret token to the HTTP header or query of the request. The data goes over HTTPS.
https://server.com/mydata?secret=my_secret
Is there a better approach?
You could try an approach where the client is only allowed X number of requests per time period (based on IP address or username)
HTTPS is extremely easy to man in the middle on a device you control. You can do SSL cert validation, but there is always someone out there with more time, so best off to handle it server side.
Distribute and use your own SSL certificate.
Apps that transfer sensitive customer data, like credit card and payment information, must be protected from man-in-the middle attacks. The best protection is a mutual authentication scheme, where certificates are exchanged to make sure the app is connected to a trusted server and to make sure the server is connected to a trusted app.
Then only individuals (who have presumably installed your application) have access. If someone digs through the code and gets the public certificate then they can impersonate the client; but at that point they win anyway and two-factor authentication should be explored.

How can a client app using HTTPS be tested for protection against a MITMA?

I have an iOS client app which connects to a server using HTTPS.
I've added code in the client to verify the identify of the server.
How can a tester testing this feature test that it is now secure, how can they for example create a MITM situation and check that the client rejects connects etc.?
I've tried googling for how to do this but haven't had much luck.
Can it be done using tools like Charles and proxies etc. or is messing around with a wireless router and having detailed knowledge necessary?
This might be over simplification for your solution, but concepts might help.
A web browsers extracts the name of hosts from embedded certificate and do a comparison of host name that we're trying to connect with. If validation fails, we usually see a security warning. For ex: we can connect with facebook by either typing https://www.facebook.com or by typing https://173.252.100.16/. When we choose second option, we get a security warning.
Your program must be using SSL client socket to connect with HTTPS server. The socket must be having capability to extract the hostname from the embedded certificate. Once you get that, compare that with valid HOST NAME that your program is trying to connect with. If it matches, let request proceed, If not, abandon that session.
To re-create MITM, your web server can use a self signed certificate that can be issue to whatever host name you want, but the IP of server could be 127.0.0.1 (for example). Since there is a mismatch between the host name and actual IP, we can probably simulate the MITM situation.
I'm assuming that digital certificate can't be forged in this case.

Is a https connection recommended for server receipt verification under iOS

I'm setting up a server to do receipt verification for IAP on the App Store.
My question is: Should I make the connection between the iOS device and my server as a https connection, or does http suffice? All the examples I seen people are just using http.
It seems that if I use http, then it's venerable to a someone redirecting the DNS. Or does that not matter? Seems like it would.
Of course, I'm such small potatoes that it's probably not worth the hassle.
It is always desirable to use https (encrypted) connection when you are passing some credentials or sensitive information such as financial transactions. May be it is not possible for anyone to mangle the transaction itself but still, you are breaching the confidentiality aspect of financial transactions which your client might not like.
However, it is not just https which can help, you can also implement your custom encryption in the application to make the communication secure (may be the security is not strong but does work in cases where you really do not need an overkill). Try to encrypt the data with a pre-shared key and decrypt it on the server (which I do myself many times).

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.

ios generate application specific key

I'm working on an ios application without authentication. Now I would like to protect my server API from calls other then my ios application. A possible solution would be to have the application generate a unique key (based on the appname and the signing), which is not stored on the device since this is the main problem. I could think off an application logic that does some protection combined with some file encryption but the problem is that somewhere something is stored (ex public key can be stored in keychain but still not safe for my API-hackers).
Anyone any tips/advice on how I can handle this ?
thanks in advance
In short, there is no 100% secure way to make sure that the request comes from your application, if the key is available to the iPhone, it's available to extract from the iPhone.
You can make it reasonably safe by calculating a key runtime from info in the application as you say and communicate it over SSL, but a determined attacker can always reverse engineer the key generation too.
What you want to do is employ mutually-authenticated SSL, so that your server will only accept incoming connections from your app and your app will only communicate with your server.
Here's the high-level approach. Create a self-signed server SSL certificate and deploy on your web server. You can use freely available tools for this, like keytool, and I think (but don't know for sure) that Apple includes a tool for this with the iOS SDK. Then create a self-signed client and deploy that within your application in a custom keystore included in your application as a resource. Configure the server to require client-side SSL authentication and to only accept the client certificate you generated. Configure the client to use that client-side certificate to identify itself and only accept the one server-side certificate you installed on your server for that part of it.
If someone/something other than your app attempts to connect to your server, the SSL connection will not be created, as the server will reject incoming SSL connections that do not present the client certificate that you have included in your app.

Resources