How do I enable Application Transport Security (ATS) restrictions - ios

How do I, Ensure ATS is enabled within the iOS mobile application so that confidential information sent between the application and the back end servers are secured and not to be intercepted by man­-in­the­-middle style attacks.
Below is what I already set but still Fails for the penetration test.enter image description here

Preventing Man-in-the-Middle Attacks in iOS with SSL Pinning.
Restricting the set of trusted certificates through pinning prevents attackers from analyzing the functionality of the app and the way it communicates with the server.
Types of SSL Certificate Pinning
Pin the certificate: You can download the server’s certificate and bundle it into your app. At runtime, the app compares the server’s certificate to the one you’ve embedded.
Pin the public key: You can retrieve the certificate’s public key and include it in your code as a string. At runtime, the app compares the certificate’s public key to the one hard-coded in your code.
There are multiple blogs available on topic of SSL pinning. for your reference attaching one
Please go through this to understand SSL pinning

Related

With iOS push certificates, why does having an SSL certificate allow Apple to know that its your server they're connecting with?

I'm reading this article on iOS push certificates, and I'm confused about this paragraph:
Your backend sends notifications through Apple's servers to your application. To ensure that unwanted parties are not sending notifications to your application, Apple needs to know that only your servers can connect with theirs. Apple therefore requires you to create an SSL certificate to be able to send push notifications.
My understanding of SSL certificates is that if a server has one, that server is able to encrypt data that it sends to a device. But it says here Apple needs to know that only your servers can connect with theirs. I don't understand how having an SSL certificate ensures that. Does anyone have any insight?
The article shouldn't have used the term SSL Certificate. SSL is the Secure Sockets Layer (which was superseded by TLS many years ago). SSL and TLS define the handshake that is used to negotiate encryption on a connection.
Enabling SSL on a web server required you to have a certificate to verify your server's identity and so this became known colloquially as an "SSL certificate".
While it isn't often used on the web, in SSL/TLS both parties can present a certificate so that there is mutual authentication.
What you typically have is actually an x.509 certificate. This is the case with the push notification service.
An x.509 certificate contains some information including the identity of the certificate holder, their private key and a signature from a trusted party that can be used to verify the information.
For push notifications, the developer generates a certificate request and submits this to Apple who sign it with their private key. Apple is the trusted party in this case.
When this certificate is subsequently presented to Apple's server they can verify that signature using their public key to confirm the identity of the connecting party.
You have has encrypted the message with their private key (Apple can decrypt it with the public key included in the certificate).
What this means is, that as long as the developer has kept their private key secure (which is why you wouldn't connect directly to the push service from your app, for example) then Apple can be sure of the identity of the server making the connection.
If someone was trying to impersonate your server then, as long as you have kept your private key secure, they can't encrypt the data properly. If they use a forged certificate that uses a public/private key pair known to them then the signature on the certificate won't be valid and Apple will reject it.

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.

Would iOS AFNetwork SSL Pinning mode provide additional security bonus if valid certificate deployed

As per my understanding, SSL Pinning is to compare the public key or certification of a server with the copies bundled in the client beforehand.
I saw in Stackoverflow that many developers use SSL Pinning by AFNetwork libraries, but most of them use it along with a self-signed certificate.
I have bought a valid certificate from a CA and passed the test to verify it worked fine. I mean, I set the following and it worked
...
_sharedHttpsInstance.securityPolicy = [AFSecurityPolicy policyWithPinningMode:AFSSLPinningModeNone];
_sharedHttpsInstance.securityPolicy.allowInvalidCertificates = NO;
...
What I am wondering is that if set the Pinning mode to AFSSLPinningModePulicKey, my application would be more secure in communication with the server in addition to what the valid certificate have provided?
thanks a lot.
I'm don't know the exact implementation of SSL pinning in iOS, but in principle pinning provides definitely more security than the default verification against a set of builtin certificate agencies. By default systems trust more than 100 different CA from all over the world and each of the CA has the ability to issue any certificate it wants, even if another CA has already issued the same or a similar certificate. So if any of these 100+ CAs gets compromised they can issue a certificate for your domain, which would pass the checks in your application unless you use certificate pinning. Such compromises happened in 2011 with DigiNotar (no longer existent because of that) and Comodo (was too big to fail).
Probably the most prominent user of certificate pinning is Google Chrome, where it is used for the google domains and this helped to detect the compromises of DigiNotar and Comodo.
A downside of certificate pinning might be, that the application will stop working inside networks which do SSL interception for security reasons. Google Chrome seems to deal with this situation by accepting the certificate if it is signed by a CA explicitly added by the user (i.e. no builtin) alternatively to the pinning checks.
Another question which might be interesting is if SSL pinning is secure 'ENOUTH' for 'Most' of the application, even if working along with self-signed certification?
Checking against a fixed certificate or public key (e.g. certificate pinning with or without self-signed) is more secure than only checking if the certificate is signed by any of the 100s CAs trusted by the system. And as long as the developer has full control about both sides (e.g. application and server) it also scales well. The only advantage of additionally using the usual infrastructure is the use of the certificate revocation mechanism. But because the developer has control of the application (s)he could just replace the appplication in case the certificate gets compromised. So yes, in most cases it is secure enough do do SSL pinning with a self-signed certificate and it is more secure than using the standard certificate validation without pinning.
It's very difficult to say categorically whether pinning is better or worse, since it shifts the risk to a different party.
Pinning will essentially protect you better against a potential breach in any of the CA you trust. If a CA is compromised and made to issue a certificate for the host you're trying to contact, pinning will protect you against that because you will compare with the specific reference you've pinned, instead of going through the CA.
The downside is that it will prevent you from using the mechanisms in place at the CA to deal with a compromised host: certificate revocation. If the host's private key is compromised, going through the PKI verification mechanism should allow you to check for revocation, and be warned that such a problem happen. In contrast, you won't be able to know that with pinning, since you're not going through the CA to check the certificate at all.
Of course, you could combine both approaches, but this could cause additional problems (you'd need a strategy to deal with conflicting outcomes in both evaluations, otherwise a compromised CA revoking a valid cert could cause a DoS).
I don't know whethet AFNetworking's pinning mechanism replaces the PKI validation or complements it.
In general, choosing between using pinning or PKI validation depends on whether you think that particular host's private key is more or less likely to be compromised than the CAs you trust.
Another downside of pinning is that you need to update the application (or let the user "re-pin") every time the server certificate (or at least the key-pair, depending on what you've pinned) is changed legitimately. It's probably not a bad idea to re-key once in a while.
(To be clear, I'm not saying that CAs are better, just that pinning changes the set of problems.)

How to compare SSL certificates using AFNetworking

In my iPhone app I'm using an https connection with a self-signed SSL certificate to download sensible data (username and password) from a server.
This app is for private use only, it is not meant for production.
I'm using AFNetworking to manage the https connection but, since my certificate isn't signed from a CA, in order to make it work I had to add the following to the header of the AFURLConnectionOperation class:
#define _AFNETWORKING_ALLOW_INVALID_SSL_CERTIFICATES_ 1
But with this my app will allow any certificate.
Is there a way to allow only the certificate from my server maybe bundling it in the app and comparing it with the certificate provided by the server in the https connection?
And if it were possible, would there be any significant advantage in terms of security?
I'm very new to security and I'm kind of confused.
The term you're looking for is SSL Pinning, where the app verifies that a known certificate or public key matches one presented by a remote server.
AFNetworking supports both pinning with certificates or public keys. You'll need to add the certificate(s) or public key(s) to your app's Bundle, and enable the feature by setting either the defaultSSLPinningMode property on AFHttpClient or the SSLPinningMode property on AFURLConnectionOperation.
You can pin using AFSSLPinningModePublicKey or AFSSLPinningModeCertificate. AFSSLPinningModeCertificate means that the server's certificate must exactly match one of those in the bundle.
AFSSLPinningModePublicKey is more liberal and means that the server's certificate must match for any public key in the bundle, or any public key attached to certificates in the bundle.
There's an example of setting the pinning mode in the AppDotNet example.
To expand a bit on David's answer with respect to AFSSLPinningModePublicKey versus AFSSLPinningModeCertificate. Ideally, you would pin the public key and not the certificate. That's because some sites and services, like Google, rotate their certificates every 30 days or so. But they re-certify the same public key.
The certificates are rotated frequently to keep the size of the CRL small for mobile clients. But they re-certify the same public key (rather than creating a new one) to allow for key continuity testing.
Public key pinning is why tools like Certificate Patrol miss the mark. The certificate is expected to change; the public key is not.
Public key pinning is a lot like SSH's StrictHostKeyChecking, if you are familiar with it.
OWASP has a write-up on it too at Certificate and Public Key Pinning.

Cryptographic Keys exchange between client and server

I have seen many examples on verifying client or server certificates using Security framework APIs but this will solve only problem of Identification of security features but what about Confidentiality of data? How do I exchange private and public keys between client and server? What about Interception, Modifications, or Fabrication attacks? What if someone pretending and sending correct certificate as expected by client?
Identification is provided by verifying the cert as you note. Confidentiality is provided via encryption. Authentication is provided by signing the data. Together they are often implemented via TLS over a network connection.
In short, if you properly implement and deploy HTTPS, and validate your certificates, then you will get all of the things you're describing. NSURLConnection will do almost all of this for you by default if you just use an "https" URL.
If you deploy a certificate on the server and protect its private key, then it is not feasible for an attacker to pretend to have that certificate. Only the server has the server's private key (it is up to you to protect the private key from copying or theft).
A typical approach is to use a commercial certificate, in which a certificate authority (CA) like Verisign attests that the private key was issued to the owner of a given host (known as the CN or common name). This is a simple-to-use approach and generally cost effective. Go to one of the well-known CAs and buy a cert.
However, you can also create your own public/private server keypair, protect the private key, and distribute the public key in your client. You can then configure your client to only accept that one certificate and no others. This is actually more secure than the commercial certificate. For an example of this, see SelfCert. This is from my CocoaConf-RTP-2012 talk. I'll be giving a similar talk at CocoaConf-DC-2013. It is also discussed at length in chapter 15 of iOS:PTL.
Client certificates are less common. They are used to authenticate the client, not the server. For a client certificate to work correctly, each client must have its own certificate. You can't ship a private key as part of your bundle. If you do, anyone can use that private key to impersonate a client. (Conversely, it is completely fine to put the server's public key in the bundle. It's public; you don't care who sees it.)
With CFNetwork, after connecting, you would need to use CFReadStreamCopyProperty to fetch the kCFStreamPropertySSLPeerTrust. You could then evaluate the returned SecTrust object. That said, I recommend the NSURLConnection code if you can use it. If you need lower-level access, you could still use NSStream. Jeff Lamarche discusses this in NSStream: TCP and SSL. But I'd recommend a tool like AFNetworking or CocoaAsyncSocket instead if you need lower-level control over TCP+SSL.

Resources