Fixing HTTPS CA Cert Issues
Updated Fri 2018-01-26 | 816 words
- How Firewalls intercept secure traffic
- The Problem with VMs
- Find the Certificate (on a Mac) (with FireFox and Keychain Access)
- Push the certificate
- Use the Certificate at User level
- Use the Certificate at System level (Red Hat / CentOS 7)
Disclaimer: I'm very new to understanding SSL, and I haven't yet put in the effort to be authoritative about this subject. This post describes how to work with a modified chain of trust from a VM without the last certificate installed.
Websites (and HTTPS requests in general) use a system called SSL Certificates to
verify that a URL visited is actually being served the legitimate provider for
it (as opposed to someone hiding between your computer and the provider and
capturing your data). They also encrypt your data so no one else can read it. SSL
Certificates are usually installed on the Operating System by the vendor (as far
as I know), but they can be updated and new ones can be installed. On Linux,
this is usually the ca-certificates package.
How Firewalls intercept secure traffic
In a corporate environment, the security department never likes the fact that encrypted information can be passed between employees and outside websites. The way I understand this, they intercept requests going out (usually at the firewall level) decrypt them, inspect them for naughtiness, then re-encrypt them and complete the request. When the answering request comes from the website, the firewall does the same thing. Here is a diagram:
Parties Involved:
Client(think desktop user)FW(firewall at the edge of the corporate network)Site(google.com, facebook.com or any other site the Client is visiting) (this could also be an API)
Non-inspected Flow:
Clientcreates encrypted request with the CA Cert pre-installed forSiteand sends it toSiteSitedecrypts it with its own certificate, creates a response, encrypts it, and sends it backClientdecrypts the response.
Inspected Flow:
In the inspected flow, the client is pre-installed with a "universal" certificate and the firewall is installed with the coordinating certificate. It uses this cert to decrypt the request, does it's thing, then encrypts it with the certificate for the website.
Clientcreates encrypted request with the CA Cert pre-installed forFWand sends it toSiteFWintercepts request, decrypts it with its coordinating certificate, inspects it, re-encrypts it with the certificate forSite, and sends it toSiteSitedecrypts it with its own certificate, creates a response, encrypts it, and sends it backFWintercepts request, decrypts it with its coordinating certificate, inspects it, re-encrypts with it's certificate, and sends it toClientClientdecrypts the response.
If you study these flow, you'll notice that this is pretty much transparent to
Client. Client doesn't have to do anything special to get it's traffic
inspected.
The Problem with VMs
However, this becomes a problem if, in the development process, you make a
request from a VM hosted on your machine (a sub-client of Client, kinda). In
this case, the firewall intercepts the request and can't decrypt it because it
wasn't encrypted with the firewall's certificate.
To fix this, you can either disable certificate checking (which means you can't
be reasonably sure you aren't going to a fake website- very bad) or you can add
the Client's 'firewall certificate to the VM's store of them. This post is
really about how to find that certificate, put it on the VM, and use it in your
code (specifically Python's requests library).
Find the Certificate (on a Mac) (with FireFox and Keychain Access)
To find the certificate, open Firefox and go to a website that supports HTTPS (for example Google), and click the green lock in the URL bar.

Use the buttons to export the certificate:
- the arrow on the right side of the lock popup
- "More Information"
- "View Certificate" (in the Security Tab)
- Switch tabs to Details in the Certificate Viewer
- Export...
Save it somewhere you can find again with a nice descriptive name.
If you open the certificate in a text editor, you'll see something like the following:
-----BEGIN CERTIFICATE-----
awScGmdnsbolcfUlYCvZRMFHwcTIcEuEzmahqBoKWqCPHYoLucnDfuKgoYqiLKDC
XJHFHBkInJfshLLgyCDXypjDDlgHHpYJvquWoBNTypJCWNWIwxWZCVbdoDiJBbAg
... more lines
-----END CERTIFICATE-----Push the certificate
Of course, you can simply scp the certificate:
scp path/to/cert.crt vagrant@vm_ip:path/to/cert.crt
Or, if you're using Ansible to manage the VM, you can use the copy module to
put it on:
- name: Push CA Certs to VM
copy:
force: false # Don't overwrite a file already there
src: path/to/cert.crt
dest: path/to/cert.crtUse the Certificate at User level
In the
requests
library, you can point to your certificate with the verify
keyword parameter:
import requests
response = requests.get('https://www.google.com', verify='path/to/cert.crt')
And then, of course, you can do whatever you want with the output.
Use the Certificate at System level (Red Hat / CentOS 7)
If you don't want to pass path to the certificate every time you want to use it,
you need to place it in the /etc/pki/ca-trust/source/anchors directory and run
the update-ca-trust extract. commmand (as explained in man update-ca-cert).
I use the following ansible snippet to this:
- name: Install custom cert so I can use https
become: true
copy:
src: /path/to/custom.crt
dest: /etc/pki/ca-trust/source/anchors/custom.crt
mode: 0777 # that's what the crts there are..
- name: Extract custom cert
become: true
command: update-ca-trust extract
So, that's how I deal with certificates in VMs.