lionheart / openradar-mirror

A mirror of radars pulled from http://openradar.me/.
245 stars 17 forks source link

716337334: Review of Manual OCSP Requests for SecTrustEvaluate (iOS makes OCSP requests outside of NSURLProtocol) #21303

Open openradar-mirror opened 5 years ago

openradar-mirror commented 5 years ago

Description

DESCRIPTION OF PROBLEM

OCSP requests do not follow NSURLProtocol subclassing. Therefore OCSP requests are not proxied when using an NSURLProtocol subclass to proxy all traffic.

Issue in more detail: https://github.com/OnionBrowser/OnionBrowser/issues/178.

Our current workaround is to inspect the X.509v3 certificate being authenticated for OCSP URLs and then make the requests ourselves; subsequently attaching the response with SecTrustSetOCSPResponse(). Reference: https://github.com/Psiphon-Labs/OCSPCache.

Our Solution

In our implementation we do the following:

  1. Check if there is a pinned OCSP response

    • Call SecTrustEvaluate with revocation policy SecPolicyCreateRevocation(kSecRevocationOCSPMethod|kSecRevocationRequirePositiveResponse|kSecRevocationNetworkAccessDisabled)
    • If SecTrustEvaluate succeeds, assume there was a pinned OCSP response
  2. Make OCSP request manually through local proxy

    • Inspect leaf X.509v3 certificate of serverTrust in URLSession:task:didReceiveChallenge:completionHandler: for OCSP URLs
    • Make OCSP requests and attach OCSP response to trust
    • Call SecTrustEvaluate with revocation policy SecPolicyCreateRevocation(kSecRevocationOCSPMethod|kSecRevocationRequirePositiveResponse|kSecRevocationNetworkAccessDisabled)

Note: Since we are caching OCSP responses, but do not know when iOS considers responses valid/invalid we only evict responses when SecTrustEvaluate fails with an OCSP response fetched out of band. If the response we attach was cached then we make another remote request for a new response. This can be seen here: https://github.com/Psiphon-Labs/OCSPCache/blob/b945a5784cd88ed5693a62a931617bd371f3c9a8/OCSPCache/Classes/OCSPAuthURLSessionDelegate.m#L196-L216.

  1. Fallback on CRLs

Questions

STEPS TO REPRODUCE

  1. Create NSURLProtocol subclass which proxies all traffic through a SOCKS or HTTP proxy by setting connection proxy dictionary (https://developer.apple.com/documentation/foundation/nsurlsessionconfiguration/1411499-connectionproxydictionary?language=objc)

  2. 
    SecPolicyRef policy = SecPolicyCreateRevocation(kSecRevocationOCSPMethod);
    SecTrustSetPolicies(trust, policy);

SecTrustResultType trustResultType; SecTrustEvaluate(trust, &trustResultType); // triggers plaintext OCSP request outside of proxy



---

Note: There are tests in https://github.com/Psiphon-Labs/OCSPCache which shed some light on implementation details and expected behaviour.

-
Product Version: iOS 8+
Created: 2019-07-09T15:46:04.950021
Originated: 2019-07-09T00:00:00
Open Radar Link: http://www.openradar.me/716337334