ATS and SSL pinning / own CA

Hi,


we have communication app, that connects to our servers. For better security, we implemented own CA and we are using SSL pinning within the app, so that only connection to servers that are certified by our CA are valid (so we walidate, if in the server certificates chain is root certificate of our CA, that we bundle with our app). This is IMHO more secure than using classic CA validation, avoids man in the middle attacks and so.


However, it looks like this approach is not compatible with ATS, I have to use NSExceptionAllowsInsecureHTTPLoads for that domains, but this is too wide aothorization for those domains, that I don't need. Is there any better approach in ATS how to solve this? I don't want to lost this SSL pinning security. Do you thing this exeption will be fine after 1.1. 2017?


Thanks,


Mildi

Replies

However, it looks like this approach is not compatible with ATS …

Correct.

Is there any better approach in ATS how to solve this?

ATS represents a base level of security checking, but you can do your own security checks in addition to those provided by ATS. So, my recommendation is that you use a CA-issued certificate for your server, which will make ATS happy, and then do your own certificate pinning checks, which will make things even more secure.

IMPORTANT While certificate pinning is clearly more secure, it’s not without its down sides. Your app will break if you change CA, or if you have to revoke your private key for some reason, or your app is deploying in certain enterprise environments, and so on.

When you choose a CA, consider that we’re adding support for certificate transparency in the upcoming OS releases. See WWDC 2016 Session 706 What’s New in Security for details.

Share and Enjoy

Quinn “The Eskimo!”
Apple Developer Relations, Developer Technical Support, Core OS/Hardware

let myEmail = "eskimo" + "1" + "@apple.com"

Hi Eskimo,


thanks for reply. Unftunatelly, when using "official" CAs, we lost the ability to have 100% control about our certificates. We now do SSL pinning agains our created CA root certificate, that we have under the control. This is exactly for reasons your wrote in "downsides" part of reply.


It is shame, that NSExceptionAllowsInsecureHTTPLoads is so wide and in my case not realy describes security state of the app.

It is shame, that NSExceptionAllowsInsecureHTTPLoads is so wide and in my case not realy describes security state of the app.

Quite. Improving this would require explicit support for custom CAs and certificate pinning inside ATS. I raised this issue with the ATS engineering team back when ATS was first introduced. They were very much opposed to the idea, although I never fully understood the reason why. If you’d like to see the system support this, you should file an enhancement request describing your requirement. Please post your bug number, just for the record.

Having said that, the fact is that the end of 2016 deadline is looming and it’s unlikely that ATS will change significantly before that. You will need to decide how you’re going to deal with that reality.

Sorry I don’t have better news.

Share and Enjoy

Quinn “The Eskimo!”
Apple Developer Relations, Developer Technical Support, Core OS/Hardware

let myEmail = "eskimo" + "1" + "@apple.com"

Hi Quinn,

For improved security and to avoid the 'downsides' you mention above we, as 'sarsonj2', have backend with self-signed certificate and have implemented pinning in client


However, when I do not include the NSAppTransportSecurity key into the .plist at all (so that ATS is full enabled),

I am still getting the canAuthenticateAgainstProtectionSpace and didReceiveAuthenticationChallenge callbacks.

This means I am still able to override server trust evaluation – and I can communicate to our self-signed backend.

I have tested this on devices having iOS 9.3.3 and iOS 10-beta so ATS should take control of connections' security.


How is it possible to override trust evaluation given that we have this note in docs:

With ATS fully enabled, you cannot override the default HTTPS server trust evaluation.


Br

_rolm_

How is it possible to override trust evaluation given that we have this note in docs:

With ATS fully enabled, you cannot override the default HTTPS
server trust evaluation.

To start, that quote from the docs is misleading. When ATS is enabled for a server you still get server trust authentication challenges (

NSURLAuthenticationMethodServerTrust
) and you can use that to increase security. However, you can’t use this to decrease security, that is, ATS provides a minimum level of security for a domain.

I recently filed a bug against the docs to clarify this (r. 27844180).

This means I am still able to override server trust evaluation – and I can communicate to our self-signed backend.

I just tested this here in my office and I definitely see ATS fail the connection even though my authentication challenge handler is specifically allowing it. It’s possible that something on your device is affecting your test (a cached result, or perhaps the server’s cert is installed on the device). Please re-test on a clean device.

Note A good way to do ATS tests on a clean device is to test in the simulator after a reset (Simulator > Reset Content and Settings). The simulator is not perfect by any means, but for ATS testing it’s pretty darned good.

Share and Enjoy

Quinn “The Eskimo!”
Apple Developer Relations, Developer Technical Support, Core OS/Hardware

let myEmail = "eskimo" + "1" + "@apple.com"

Hi Quinn

Thanks for the details, but things are still a little bit unclear though.

The statement

When ATS is enabled for a server you still get server trust authentication challenges (NSURLAuthenticationMethodServerTrust) and you can use that to increase security.

looks to be in contradiction with an earlier comment in this thread:

Correct.  If the server is in a domain with ATS enabled, the connection will fail before these delegate callbacks are issued.

Are there any subtle conditions specifying if the callbacks are called or not for a domain with enabled ATS?


As you suggested I have now retested my code on a clean simulator – I observed exactly the same behavior as before, namely

1. If I use the default system truststore (unmodified) in didReceiveAuthenticationChallenge - then ATS fails the connection.

SecTrustRef trust = challenge.protectionSpace.serverTrust;
[challenge.sender useCredential:[NSURLCredential credentialForTrust:trust] forAuthenticationChallenge:challenge];

This is expected since the self-signed certificate is not trusted by default.

Is this what you do in your test that fails?

2. If I however really override, by setting custom anchor certificates to the truststore using SecTrustSetAnchorCertificates(…) - then the connection is accepted and the app is able to communicate to its self-signed backend.


Could you please confirm that the above is the expected and correct behavior?

Can you also confirm that this behavior will remain unchanged in future versions of iOS?


Br

_rolm_

Thanks for the details, but things are still a little bit unclear though.

Indeed. I’d like to discuss this with you one-to-one. Please email me directly at the email address in my signature.

Share and Enjoy

Quinn “The Eskimo!”
Apple Developer Relations, Developer Technical Support, Core OS/Hardware

let myEmail = "eskimo" + "1" + "@apple.com"

[I’m] wondering [if] this is the expected behavior or something that might be changed in future iOS versions.

This is a bug in the interaction between ATS and the NSURLSession delegate callback (r. 27866669). The expected behaviour is as I posted back on Aug 15, namely:

When ATS is enabled for a server you still get server trust authentication challenges (

NSURLAuthenticationMethodServerTrust
) and you can use that to increase security. However, you can’t use this to decrease security, that is, ATS provides a minimum level of security for a domain.

If you want to talk to a server with a self-signed certificate, you must disable ATS for that server (and deal with any App Review fallout from that). My recommendation, however, is that you avoid setting up a server in this way. In my experience there are three common reasons for using a self-signed certificate, and all of them have alternative approaches that don’t require ATS exceptions:

  • cost or hassle of a CA-issued certificate — Getting a CA-issued certificate is not necessarily expensive or difficult; indeed, it’s free and easy if you take the Let’s Encrypt path.

  • enterprise — In this case you should have your enterprise CA issue your server a certificate, and then install your enterprise CA’s root certificate on your device via MDM.

  • testing — Here you can set up your own test CA, have it issue a certificate for your server, and install your test CA’s root certificate on your device. If you don’t have existing experience with running a CA, there are facilities built in to the Mac to do this; see Technote 2326 Creating Certificates for TLS Testing.

Share and Enjoy

Quinn “The Eskimo!”
Apple Developer Relations, Developer Technical Support, Core OS/Hardware

let myEmail = "eskimo" + "1" + "@apple.com"

Quinn,

isn't his approach incompatible with ATS only because he's not having his users install his self-signed CA certificate in iOS CA keychain store? If he did that it should work okay, correct?


After all this is the approach taken by penetration testing tools such as BURP, which provide the tester with a BURP CA certificate as well as a straightforward way to install it in the iOS CA certificate store.


As you know, when you install BURP's CA certificate in an iOS device, all https traffic to/from that device can be easily monitored in the proxy machine via BURP's MITM, unless of course the app has certificate pinning functionality.

Thanks,

Neal

isn't his approach incompatible with ATS only because he's not having his users install his self-signed CA certificate in iOS CA keychain store?

I’m not sure who “he” is in this context, so I’m going to make two general statements:

  • ATS’s specified behaviour is that, if ATS is enabled for a domain, developer code should not be able to decrease security for that domain. Current systems have a bug that allows this to happen (r. 27866669), and we’re in the process of fixing that bug.

  • One of ATS’s security checks is that the server’s certificate must be trusted by the system, that is, it must be issued by a CA whose root certificate is trusted by the system. The set of trusted root certificates includes those built in to the OS and those configured by the user.

If the above doesn’t address your point, please post back.

Share and Enjoy

Quinn “The Eskimo!”
Apple Developer Relations, Developer Technical Support, Core OS/Hardware

let myEmail = "eskimo" + "1" + "@apple.com"

Hi Quinn,

My apologies, I was referring to the original poster sarsonj2. Your second bullet point addressed my point, which was that if sarsonj2 simply made the user trust his company's custom CA certificate (by installing in the iOS device), ATS would not complain about anything at all.


i was just pointing out that your original reply to him did not provide him with that option.


All the best,


--Neal