1

We're using WinHTTP to send API calls from our client. Now according to Common Criteria, FCS_TLSC_EXT.1.2 assurance activity Test 2, if certificate contains a valid CN (common name) but invalid SAN(Subject Alternate Name), the connection should fail.

Test 2: The evaluator shall present a server certificate that contains a CN that matches the reference identifier, contains the SAN extension, but does not contain an identifier in the SAN that matches the reference identifier. The evaluator shall verify that the connection fails. The evaluator shall repeat this test for each supported SAN type.

tool we're using to generate a certificate with valid CN but invalid SAN.

However, with WinHTTP and python requests package, they accept the invalid SAN (which should not happen). There seems to be no documentation on WinHTTP as to how this can be handled. this is internal implementation of WinHTTP.

Internet explorer also fails this test and accepts the connection. However chrome does deny the connection and confirms that the certificate is invalid (which is the required behavior):

enter image description here

The test fails with python's request library as well.

We are looking for some way if this can be altered to check the issue. Or is this us only facing the issue?

Since both python and windows libraries are used commonly, is this behavior common? Has anyone else experienced this issue?

I want to know if this is how WInHTTP implements SAN check, or is it just our implementation. Also, I couldn't find any documentation on MSDN regarding SAN checking in WinHTTP.

schroeder
  • 123,438
  • 55
  • 284
  • 319
  • Please link to the relevant part of the document instead of FCS_CKM.1.1(1) as you currently do. Also, please quote the relevant part which you think claims that it should fail with invalid SAN - I cannot see such a requirement. Maybe you should provide a concrete example so one can see what you consider an invalid SAN in the context of this claim. – Steffen Ullrich Feb 27 '18 at 13:40
  • @SteffenUllrich, does this help? – Muhammad Uzair Khan Feb 27 '18 at 14:34
  • I see. your "invalid" is actually not invalid but just not matching. – Steffen Ullrich Feb 27 '18 at 14:51

1 Answers1

2

First, the issue is not about valid CN vs. invalid SAN but about a CN matching the domain vs. a SAN not matching the domain. A non-matching SAN is still a valid SAN entry.

The rule according to RFC 6125 is that the CN MUST not be checked if there is a SAN DNS entry. Additionally CN is deprecated for a long time and RFC 6125 explicitly adds that the CN MAY be checked if no appropriately typed SAN records exists and does not require it. Still, most implementations check both SAN and CN. Only Chrome does not check the CN at all since a while now. This is the primary reason the issue seems to be fixed with Chrome but not with others and this actually violates "Verification using the Common Name is required for the purposes of backwards compatibility" from FCS_TLSC_EXT.1.2.

... and python requests package, they accept the invalid SAN

As far as I can see the current version of requests ultimately uses the functionality of this ssl module in Python to validate the hostname. The code here in the latest version of Python explicitly makes sure that CN is only checked if no SAN DNS names exist. Of course, this might vary with the unknown version of Python and requests you are using.

I want to know if this is how WInHTTP implements SAN check, or is it just our implementation

While I cannot be sure because I don't know your implementation the chance is high that at least the version of WinHTTP your are using implements CN checking additionally to SAN - at least by default. This is similar to many other implementations although it does neither match RFC 6125 nor the older RFC 2818.

Steffen Ullrich
  • 184,332
  • 29
  • 363
  • 424
  • 1
    To add to Steffen's comment, there are also various RFC 5280 sections (e.g., Section 4.2.1.6) that specify SAN handling. More so, RFCs also specify that if only CN is used with server identity certificate, it must contain FQDN identifier and nothing else. SAN allows DNS-ID, SRV-ID, and URI-ID and is more flexible. – Kirill Sinitski Feb 28 '18 at 13:35
  • Im using python3.6 with requests==2.18.4 – Muhammad Uzair Khan Mar 01 '18 at 07:31
  • @steffan, can you provide reference to this: "The code here in the latest version of Python explicitly makes sure that CN is only checked if no SAN DNS names exist." – Muhammad Uzair Khan Mar 01 '18 at 07:32
  • @MuhammadUzairKhan: the only reference I have for this is the code you'll find on github. See https://github.com/python/cpython/blob/master/Lib/ssl.py#L276 – Steffen Ullrich Mar 01 '18 at 08:45
  • Just so anyone needs to know. Python requests does not parse URI SANs. – Muhammad Uzair Khan Mar 12 '18 at 11:25
  • @MuhammadUzairKhan: it is not clear why it should parse URI SAN's since the process of certificate validation only involves DNS SAN and maybe IP SAN. But now I see that you've actually used a URI-SAN in your certificate and not IP or DNS SAN. – Steffen Ullrich Mar 12 '18 at 11:34