Certificate Transparency testing

I am working on an iOS app where we were using SSL pinning with TrustKit. Recently I was tasked to remove this and implement CT.  Thou, after combing through the internet I am not sure if I implement it right. 

I used Performing Manual-Server Trust Authentication. I've set NSIncludesSubdomains, NSRequiresCertificateTransparency and NSExceptionAllowsInsecureHTTPLoads to true. I see in Xcode that it is going through the function passing it successfully.

However, I was told by the Android team, that on their side, with CT enabled, using Proxyman, they are unable to see traffic or, if the URL is presented, it shows an SSL handshake error. Where on iOS, in Proxyman, I still can see all traffic with all details. I saw this conversation https://developer.apple.com/forums/thread/720611 which says that CT was not intended to defeat proxy tools, which makes sense and confuses me even more.

How can I test this? How can I ensure that this is implemented and working as expected?

which says that CT was not intended to defeat proxy tools

Correct.

If you want your app to fail in the presence of a debugging HTTP proxy, using NSPinnedDomains.

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

Hi @eskimo, thanks for your answer. Could you please give a little background why Apple's CT implementation would accept a certificate from a custom CA without any SCTs from approved logs? "Apple's Certificate Transparency policy" [1] states the following Policy requirements:

  • At least two SCTs from currently approved CT logs with one SCT presented via TLS extension or OCSP Stapling; or
  • At least one embedded SCT from a currently approved log and at least the number of SCTs from once or currently approved logs, based on validity period as detailed in the table below.

Or is my assumption right, that CT is disabled for custom CAs and that it is no longer possible to enable it on iOS16?

[1] https://support.apple.com/en-us/HT205280

Could you please give a little background why Apple's CT implementation would accept a certificate from a custom CA without any SCTs from approved logs?

That’s a policy question, which kinda falls outside of my domain.

Having said that, as someone who uses a custom CA in a couple of different scenarios, I’m very glad it works this way; having to deal with CT would make everything more complex. And I doubt that I’m the only site admin of that opinion.

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

Hi im still confused about why i can proxy requests with iOS 16 and Certificate transparency.

As the above question.

iOS < 16: makes any SSL handshake attempt fail if I try to intercept network traffic using a certificate that is not trusted by CT.

iOS >= 16: let me intercept network traffic using a certificate that is not trusted by CT. The same happens if I remove the NSRequiresCertificateTransparency key.

What have changed in iOS 16, that makes me able to proxy my requests?

You are writing in a different thread

That’s a policy question, which kinda falls outside of my domain.Having said that, as someone who uses a custom CA in a couple of different scenarios, I’m very glad it works this way; having to deal with CT would make everything more complex. And I doubt that I’m the only site admin of that opinion.

Is this policy something that we can control, as a setting somewhere? As NSPinnedDomains is not at option for our architecture, we are kind of dependent on CT to work as proxy blocker.

As NSPinnedDomains is not at option for our architecture, we are kind of dependent on CT to work as proxy blocker.

Lemme repeat myself here: Using CT as a “proxy blocker” is not going to work. You can either use NSPinnedDomains or implement the something manually by handling the NSURLAuthenticationMethodServerTrust authentication challenge.

IMPORTANT If you do the latter, I strongly recommend that you leave the standard ATS policy in place. That’ll ensure that, regardless of any bugs in your authentication challenge handler [1], the system will enforce the ATS policy.

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

[1] Such bugs are depressingly commonplace, which is one of the reasons we introduced ATS. I once helped a household name developer with a server trust evaluation issue and, as part of that investigation, discovered that the authentication challenge handler that they’d added for testing was effectively disabling all server trust evaluation O-:

Hi Quinn, thanks for the response. Im coming back to this issue after a while and was thinking giving it a try.

So leaving the rest of the ATS untouched and just cancel the challenges that does not have the kSecTrustCertificateTransparency flag set to true. This seem to get the same behaviour as pre iOS 16.

    public func urlSession(_ session: URLSession, didReceive challenge: URLAuthenticationChallenge, completionHandler: @escaping (URLSession.AuthChallengeDisposition, URLCredential?) -> Void) {
        let protectionSpace = challenge.protectionSpace
        
        if let serverTrust = protectionSpace.serverTrust, protectionSpace.authenticationMethod == NSURLAuthenticationMethodServerTrust {
            if let dictionary = SecTrustCopyResult(serverTrust) {
                let enabled = (dictionary as NSDictionary)[kSecTrustCertificateTransparency] as? Bool ?? false
                if !(enabled) {
                    completionHandler(.cancelAuthenticationChallenge, nil)
                    return
                }
            }
        }
          
        completionHandler(.performDefaultHandling, nil)

    }

Is this how you meant, do you see any other risks of doing it like this?

Certificate Transparency testing
 
 
Q