blogng/blog/2019-08-06-trouble-with-ocsp.markdown
2019-08-07 17:15:33 +02:00

4.5 KiB

layout title date comments tags
post Trouble with OCSP 2019-08-06 true ocsp, tor, security, privacy

Trouble with OCSP

This is a post about side channel information leakage that was present in OnionBrowser in some OCSP flows. This is not a exhaustive documentation of OCSP protocol.

Digital certificates are issued for a longer timespan. It reduces maintaince overhead. Most of the cases CAs issue a certificate and they are valid untill the expiration time.

But what are we to do when a certificate is compromised? We can re-issue a certificate, but the old one is still in the wind. Thats where Online Certificate Status Protocol comes in. It defines a way to check validity of a certificate in a timely1 manner.

OCSP2 works roughly as follows in an https connection:

  1. Client looks up the OCSP responder server from AuthorityInfoAccesssection in the certificate.
  2. Client crafts a OCSP request and sends it to OCSP responder.
  3. Responder returns the current status of the certificate, one of good, revoked or unknown

There are many other interactions defined in the OCSP ecosystem. Maybe the most important one is OCSP Stapling. In stapling the original request server sends back OCSP validation message with the certificate itself, removing the need for another seperate request.

Dissecting an OCSP Request

If the request is <255 bytes, OCSP allows it to be passed as a GET path. So a typical request looks like this

GET http://ocsp.int-x3.letsencrypt.org/MFgwVqADAgEAME8wTTBLMAkGBSsOAwIaBQAEFH7maudymrP8%2BKIgZGwWoS1gcQhdBBSoSmpjBH3duubRObemRWXv86jsoQISA6D%2BPqgUVCy3wtolHIxq%2Bk0e

The request is URL-Encoded > BASE64 encoded > ASN-1 data. After decoding, one can use ocsptool from GnuTLS to read it.

echo -n "MFgwVqADAgEAME8wTTBLMAkGBSsOAwIaBQAEFH7maudymrP8%2BKIgZGwWoS1gcQhdBBSoSmpjBH3duubRObemRWXv86jsoQISA6D%2BPqgUVCy3wtolHIxq%2Bk0e" \
	| python -c "import sys, urllib.parse as ul; print(ul.unquote(sys.stdin.read()));" \
	| base64 -d \
	| ocsptool -i
OCSP Request Information:
	Version: 1
	Request List:
		Certificate ID:
			Hash Algorithm: SHA1
			Issuer Name Hash: 7ee66ae7729ab3fcf8a220646c16a12d6071085d
			Issuer Key Hash: a84a6a63047dddbae6d139b7a64565eff3a8eca1
			Serial Number: 03a0fe3ea814542cb7c2da251c8c6afa4d1e

.. and then lookup the cert parameters

curl https://crt.sh/?serial=03a0fe3ea814542cb7c2da251c8c6afa4d1e
...
 Issuer: (CA ID: 16418)
                          commonName                = Let's Encrypt Authority X3
                          organizationName          = Let's Encrypt
                          countryName               = US
                      Validity
                          Not Before: Mar 29 00:08:51 2019 GMT
                          Not After : Jun 27 00:08:51 2019 GMT
                      Subject:
                          commonName                = check.torproject.org
...

Privacy Takes a Backseat.

Careful examination of above workflow will reveal that the OCSP flow is happening over HTTP. Most issuers seems to stick to http; possibly to avoid cyclical dependencies. This means man-in-the-middle leakage of certificates a user is validating is happening, and by extension leakage of websites user is accessing.

Onion Browser

iOS has inbuilt mechanism for checking revocations. They seem to be only enforced for EV certificates though. This is not a bad thing at all, but it creates a weird situation where it leaks urls with EV certs from Onion Browser. Semi-Official (as far as I can tell) Tor browser on iOS.

Whenever Onion Browser accesses a website with EV cert, (for e.g https://check.torproject.com), the OCSP request is routed via regular transport, not via onion network as one would assume.

I stumbled upon this accidently while inspecting requests from my iPhone with mitmproxy. The bug was reported to Onion Browser team and they have a better write up of the situation. Unfortunatly it is really hard to fix. :-(


  1. Opposed to checking againist a Certificate Revocation List. ↩︎

  2. Familier readers will note that this is plain OCSP, the non-stapling kind. ↩︎