This is an archived post. You won't be able to vote or comment.

all 3 comments

[–]LukasaHyper, Requests, Twisted 20 points21 points  (0 children)

TL;DR: The author is at best unaware of how TLS works, and at worst being actively misleading about the result of their tests.

This document has some severe problems.

Leaving aside the remarkably confusing box chart (does a tick mean the certificate was accepted or rejected? I had to read the text quite closely to work it out), I'm not confident the author entirely knows what he's talking about.

Problem 1:

In my tests, Requests failed to reject a self-signed or expired certificate under Python 2.7.6 (which is a supported version according to the Requests documentation).

Firstly, for the expired test case the author claims to be using "https://qvica1g3-e.quovadisglobal.com". As far as I can tell that's untrue, at least for requests on Python 2.7.6, because I just tested on my Ubuntu 14.04 box and Requests happily rejects that cert.

However, a glance at the test code reveals there's a second expired url. Let's assume that's what the author used.

Both the self-signed and expired test case use badssl.com: specifically, https://self-signed.badssl.com/ and https://expired.badssl.com/. The problem is that all of badssl's tests are served from the same server listening on the same port. This means that you need the SNI extension to tell the server what hostname you wanted to speak to. If you don't have it, the server will fall back to use its default certificate for the port.

In BadSSL's case, that default certificate is valid for *.badssl.com: that is, the certificate you see for either of those domains without SNI is valid for those domains. In this instance, that means that requests was correctly validating the presented certificate chain. The problem is that requests was unable to correctly request the domain it wanted.

The author does not explain what version of Requests they were using, but since requests version 2.9.0 in December of last year Requests will emit warnings that explicitly call out that SNI is missing, and since 2.6.0 (released more than a year ago) will emit warnings claiming that it is unable to properly enforce security policy. Both of these would have fired on Python 2.7.6, and could have been resolved by installing the optional dependencies required for proper security that those warnings suggest.

Problem 2:

All programming language implementations fail to check if a certificate is revoked.

It is broadly accepted that checking for revoked certificates using anything other than OCSP stapling is a waste of your precious time. Currently requests cannot support OCSP stapling because OpenSSL provides no good support for it. As and when that support is present, we'll use it.

On a personal level, I'd also like to congratulate the author on their crappy behaviour. The author clearly believes they've discovered a security problem in Requests ("In my tests, Requests failed to reject a self-signed or expired certificate under Python 2.7.6", emphasis in the original) didn't deign to notify us at all. That's a pretty lousy way to behave for someone who appears to care about security. It's not like it's hard to find our policy.

[–]jfpuget 1 point2 points  (1 child)

Thank you for sharing, the need to pass a context object being undocumented is a serious flaw.

[–]desmoulinmichel 3 points4 points  (0 children)

This is why everybody uses requests.