"ssl" module doesn't validate that domain of certificate is correct

John Nagle nagle at animats.com
Mon Apr 19 23:48:35 EDT 2010


exarkun at twistedmatrix.com wrote:
> On 05:49 pm, nagle at animats.com wrote:
>> exarkun at twistedmatrix.com wrote:
>>> On 04:51 pm, nagle at animats.com wrote:
>>>>    I'm converting some code from M2Crypto to the new "ssl" module, and
>>>> I've found what looks like a security hole.  The "ssl" module will
>>>> validate the certificate chain, but it doesn't check that the 
>>>> certificate
>>>> is valid for the domain.
>> ...
>>> It's a bit debatable.  There probably should be a way to make this 
>>> happen, but it's far from clear that it's the only correct behavior. 
>>> And, as it turns out, there is a way to make it happen - call 
>>> getpeercert() and perform the check yourself. ;)
>>
>>    "Checking it yourself" is non-trivial.
> 
> Yes.  It'd be nice to having something in the stdlib which accepted a 
> hostname and a certificate and told you if they line up or not.
>> The SSL module doesn't seem to let you read all the cert extensions,
> 
> Yes.  That sucks.  It was argued about on python-dev and ultimately the 
> people writing the code didn't want to expose everything.   I don't 
> remember the exact argument for that position.
>>    It's very bad for the "ssl" module to both ignore this check and
>> not have that mentioned prominently in the documentation.
> 
> I agree.  As I said, I think the behavior should be well documented.
> 
> Jean-Paul

    What a mess.

    The cause of the problem seems to be someone named "Bill Janssen (janssen)"
See "http://bugs.python.org/issue1589".  He shouted down attempts to put in
this check, apparently because he saw use cases for a backdoor.  He
claimed he would change the documentation, but did not do so, leaving
the backdoor enabled.

    Without host name checking, you lose all "man in the middle" protection
in SSL.

Jannsen wrote:
"Nope.  Hostname verification was never a good idea -- the "hostname" is
just a vague notion, at best -- lots of hostnames can map to one or more
IP addresses of the server."

This is an weak objection for the SSL module, since the SSL "connect"
function can take a domain name, not an IP address.  You can pass an
IP address to "connect", but if you pass a domain name, it should
be validated against the certificate.   Also, with TLS, name validation
is supposed to work even for multiple domains on the same IP address.
(But see "http://en.wikipedia.org/wiki/Server_Name_Indication", which
says that it works in most current browsers, but not Python.)

Heikki Toivonen (heikki), author of M2Crypto, wrote:

"I would definitely recommend providing as strict as possible hostname
verification in the stdlib, but provide application developers a way to
override that."

Hekki put a warning about this on his blog at
"http://www.heikkitoivonen.net/blog/2008/10/14/ssl-in-python-26/".

All major browsers make this check.  Most Python users will expect the
SSL module to do the checks a browser does.  If the user went to the
trouble to provide a certificate authority file, and specified CERT_REQUIRED,
they presumably want their connections fully validated.

But Jannsen closed the issue anyway.  Looks like a "developer in denial"
situation.

The sample code suggested for a user-level check at

http://bugs.python.org/msg58508

does not handle valid domain wildcards, which makes it unusable in practice.
It's non-trivial to do this in accordance with the spec.

Here's an example of code written by someone who wasn't aware of this bug.
"http://www.muchtooscrawled.com/2010/03/https-certificate-verification-in-python-with-urllib2/"

It's not clear if this hole made it into Twisted, or the Python
BitTorrent client.

Who's reviewing the SSL module for security?  Is anyone checking for backdoors?


					John Nagle



More information about the Python-list mailing list