Python Requests Throwing Sslerror

Curl works but python request fails with SSLError

Turns out the issue was with the certificate.
I was having self signed certificates which were not present in the OS trust store.

Python requests need the path to full chain cert not just intermediate cert for verify parameter. See requests documentation: SSL Cert Verification

After updating it, it worked without any issues.

Python requests SSL error - certificate verify failed

As already pointed out in a comment: the site has a bad SSL implementation as can be seen from the SSLLabs report. The main part of this report regarding your problem is:

This server's certificate chain is incomplete. Grade capped to B.

This means that the server is not sending the full certificate chain as is needed to verify the certificate. This means you need to add the missing certificates yourself when validating. For this you need to include the PEM for the missing chain certificate C=US, O=DigiCert Inc, OU=www.digicert.com, CN=DigiCert SHA2 High Assurance Server CA and also for the root CA C=US, O=DigiCert Inc, OU=www.digicert.com, CN=DigiCert High Assurance EV Root CA info a file my_trust_store.pem and then you can call:

requests.get("https://...", verify='my_trust_store.pem')

... but I've tried downloading the site's certificate and pointing to that file using the verify option

This will not work with normal leaf certificates. Since the SSL stack of Python is based on OpenSSL and OpenSSL expects only trusted certificate authorities in the trust store (i.e. given with verify) and a server certificate is not CA certificate it will not help to add it to the trust store.

Python Requests throwing SSLError after downloading certificate

The issue was indeed that I needed to download the certificate chain, and not just the individual certificate. I do not know how to do this with openssl as I would like, but I was able to do it in Firefox.

This is done by going to the website, clicking on the padlock next to the web address, clicking on the arrow next to the message "Connection secure", clicking "More Information", going to the "Security" tab, clicking on "View Certificate", then clicking on the download "PEM (chain)" in the "Miscellaneous" section. This is the certificate I needed to make requests.get() work properly.

python Requests SSL ERROR (certificate verify failed)

It is highly recommended to have a deeper look at the excellent documentation for requests. It has a special chapter about SSL Cert Validation which explains:

You can pass verify the path to a CA_BUNDLE file or directory with certificates of trusted CAs:

>>> requests.get('https://github.com', verify='/path/to/certfile')

Assuming that your server certificate was signed by your ca.crt you should use this for the verify parameter.

EDIT: based on the discussion it looks like that CA and server certificate used the same subject. This means that the certificate validation assumes that this is a self-signed certificate which thus results in an certificate validation error.

python requests to google.com throwing SSLError

I figured it out! TL;DR: my antivirus was doing some HTTPS/TLS filtering.

I had a look at the answer that @Juilen Cochennec linked in his comment, again, and noticed it suggested using openssl directly from the commendline to examine what certificate chain was actually being returned.

So I ran

openssl s_client -showcerts -connect googleapis.com:443

and I did not get the certificate chain I expected; the first intermediate certificate was not issued by Google but by Bullguard. It was

i:/C=GB/ST=Hounslow/L=Heathrow/O=BullGuard Ltd./OU=DevelTeam/CN=BullGuard SSL Proxy CA 

Bullguard is the name of my antivirus, so I suspected that it was somehow blocking my requests. After some research I found the precise cause, namely, Bullguard's Safe Browsing feature. It scans websites and blocks them if it thinks they are unsafe.

A subset of this is safe results, which shows checkmarks (or X's) next to results on search engines, such as Google. It appears to use HTTPS/TLS filtering to do this; it inserts itself between you and your search results so that it can modify the page with the checkmarks. Looking now, this was not even secure in Firefox; the checkmarks don't display because it can't get the safe browsing results.

The upshot is that this filtering was causing SSL errors across all google domains, which was tripping up requests. To fix all I had to do was disable safe results for Google; not even safe browsing itself, just safe results. This disabled the filtering and my requests now work again.

I hope that this helps anyone else with this problem!

P.S. I found this useful to see what the SSL certificate chain was supposed to be, which helped me to identify that it was wrong.

Python Requests throws SSL Error on certain site

... lot of people claimed adding in the optional argument "verify=False" should fix these types of SSL errors

adding verify=False helps against errors when validating the certificate, but not against EOF from server, handshake errors or similar.

As can be seen from SSLLabs this specific server exhibits the behavior of simply closing the connection (i.e. "EOF occurred in violation of protocol") for clients which don't support TLS 1.2 with modern ciphers. While you don't specify which SSL version you use I expect it to be a version less than OpenSSL 1.0.1, the first version of OpenSSL supporting TLS 1.2.

Please check ssl.OPENSSL_VERSION for the version used in your code. If I'm correct your only fix is to upgrade the version of OpenSSL use by Python. How this is done depends on your platform but there are existing posts about it, like Updating openssl in python 2.7.



Related Topics



Leave a reply



Submit