Security of SSL Pinning - ios

I have an iOS app which implements SSL Pinning. I compare the remote certificate against the locally stored certificate and proceed depending on the result of the comparison. If both certificates are equal, the URL connection is permitted. Otherwise, it is denied. My question is this: Can an attacker change the local certificate stored in the app (.ipa) with another certificate?
This would allow the attacker to see all of my requests and responses.
Thanks.

Yes, but only on jailbroken device, since on non-jailbroken device you can't view the content of the installed application.

Related

iOS - how do I get server certificate into iOS client keychain for pinning

TL;DR version: Is there any way to pass a Server certificate to an iOS client that doesn't involve also passing along the Server's private key?
I have written an iOS client app that communicates with my macOS server app (so I have control over both ends). I have implemented certificate pinning using a self-signed certificate to make things more secure. To accomplish this during development, I hardcoded the Server cert into the iOS client app and told the client to only connect to a server that gives you that exact cert during the TLS handshake. Everything is working great.
However in the real world I am selling this system as a set (1 Server, multiple clients to each customer), so I cannot hardcode a Server cert into the iOS client. My plan is to instead deliver the Server cert out of band (via email) to the iOS client like mentioned here: Making Certificates and Keys Available To Your App:
Apps can only access keychain items in their own keychain access groups.
To use digital identities in your own apps, you will need to write code to import them. This typically means reading in a PKCS#12-formatted blob and then importing the contents of the blob into the app's keychain using the function SecPKCS12Import
One way to provision an identity is via email. When you provision a device, send the associated user an email with their client identity attached as a PKCS#12 file.
My problem is that a .p12 file contains the certificate and the private key of the server - this seems very wrong to pass the private key along as well.
Is there any other way to pass the Server certificate to the iOS client that doesn't involve also passing along the Server's private key?
Thanks!!!
I was overthinking things here, the solution is actually pretty simple.
I just needed to email the Server's public certificate out of band to the client device with a custom extension like cert.myCustomExt1234. This is because the .crt extension is already claimed by iOS so you have to register your app to handle custom extensions (see apple docs here). Then in my app I can do all the logic of cert pinning using that out of band delivered Server public cert.
The key was changing the file extension to something not already claimed by iOS.

Handling SSL certificates as they are renewed on the server

I have a cert signed by a CA (Geotrust) on my server. I have the same cert installed in my app. I compare the two certs in URLSession:didReceiveChallenge:completionHandler:. But I was notified by my hosting service that I need to 'renew' the cert each year. That creates a new and different cert for me to handle in the app. Since the certs are not self-signed, do I need to embed the cert in the app for comparison with the cert as it comes from the server or does iOS's SSL handling take care of the challenge for me. Maybe I can just use server trust without looking at the cert?
I have the same cert installed in my app.
Why?
I compare the two certs in URLSession:didReceiveChallenge:completionHandler.
Why?
What you should be doing is comparing the subjectDN. That's what the signer is verifying. It's all you need.
Maybe I can just use server trust without looking at the cert?
It sounds like you're trying to do the correct thing and add an authorization step. Relying on 'server trust' just gives you authentication, i.e. the subject DN is who he says he is. Authorization checks whether that DN is authorised to use this part of the application. But you don't need to check the entire certificate for that.

Retrieving certificate stored via Safari during enrollment

How can we retrieve identity certificates received from SCEP during enrollment in objective c.
I guess the certificates are stored in KeyChain Access of the device.
PS: I read somewhere that we cannot access other apps keychain via any 3rd party app, so is it possible to get the certificates stored during enrollment process of MDM
I think you can't access it. As you correctly mentioned, it's stored in keychain. And I believe in this case, it will be stored in keychain of Safari or mdmd. And you don't have access to either of those on your device (except, if it's jailbroken).
However, if Certificate authority in your control, potentially you can write server side code which will allow query certificate (not a private key) for your device. Your application will talk to your server and it will go to Certificate authority and get a certificate associated with your device.

How to accept trusted certificate added to iOS device via iPhone Configuration Utility in application

I want my application to have the ability to accept trusted root certificates that have been added to an iOS device by using the iPhone Configuration Utility.
I added a trusted certificate to an iOS device using the iPhone Configuration Utility and confirmed that Safari accepts my self-signed certificate by sending my server a https request. However, when I make a simple test app that uses NSURLConnection to make a GET request to my server using HTTPS, I get the following error message:
"
Error - The certificate for this server is invalid. You might be connecting to a server enter code here`that is pretending to be “myserver” which could put your confidential information at risk.
"
I imagine that my iOS app is sandboxed, and does not accept the self-signed certificate by default. I've tried manipulating code in willSendRequestForAuthenticationChallenge to accept the self signed certificate without success. I was hoping that someone else has figured out how to do this. I do not want to accept all self-signed certificates. I only want to accept self-signed certificates that have been configured to be trusted on the device.

If a server has a trusted certificate, What steps are needed to hit that link on IOS using NSURLConnection?

The Application i am working on needs to connect to a webservice over https, The certificate is trusted and valid.
I have used NSURLConnection is previous projects to use soap over http
Can anybody please point the difference between the two above mentioned scenarios,
I also need to understand what exactly happens when connecting over https, is the certificate stored automatically on the device, how does ssl handshake happen.
Any Pointers in this direction will be really helpful.
Regards,
Ishan
I need some clarification. Is the certificate signed by Apple for use with notifications or is it signed by an SSL root certificate authority (like VeriSign)?
Apple signed certificates are only to be used with WebServer to Apple Server communications like the Apple Push Notification Service. They are not intended for iOS device to WebServer.
A SSL certificate signed by a SSL root certificate authority should just work.
I think you are looking for an HTTP over SSL/TLS primer. So, here it goes.
HTTP is an unencrypted channel. The request and response are in a plain text data stream. HTTPS is an encrypted channel. The request and response are in a data stream encrypted using a shared master key. The magic of SSL/TLS is how this encrypted channel is created.
First, the client and server say hello to each other (in a clear channel).
Next, the client downloads the server's public certificate (in a clear channel).
At this point, the client has some work to do. It needs to verify the certificate. It needs to know that it understands the certificate, that the date range is valid, that the certificate is signed by a trusted certificate authority, and that the certificate has not been revoked.
Now, the client knows that it can trust the server.
Next, It sends a few short messages encrypted with the public key of the server (which is in the server's public certificate). These messages can only be decrypted by the server's private key (which only the server knows about). These messages allow the client and the server to negotiate a master key.
Finally, the client and the server begin the normal HTTP request and response using the newly created encrypted channel.
I hope this is what you are looking for. For a more detailed description see: http://www.moserware.com/2009/06/first-few-milliseconds-of-https.html
If the certificate was issued by a chain of certificate authorities whose root is trusted by Apple, then there is nothing to do. The iOS device will accept the certificate, as long as it is otherwise valid (ie not expired, not revoked, etc).
If the CA chain's root is not trusted by Apple, you will need to download the root's certificate to the phone. This can be done (I think) via the iPhone Configuration Utility. Enterprise provisioning scenarios undoubtedly support this also.

Resources