New issue
Advanced search Search tips
Note: Color blocks (like or ) mean that a user may not be available. Tooltip shows the reason.

Issue 824799 link

Starred by 1 user

Issue metadata

Status: Fixed
Owner: ----
Closed: Mar 2018
Cc:
Components:
EstimatedDays: ----
NextAction: ----
OS: Linux , Android , Windows , Chrome , Mac , Fuchsia
Pri: 2
Type: Bug-Security



Sign in to add a comment

Security: Bug in X509_VERIFY_PARAM_set1_host() with namelen 0

Reported by tira...@gmail.com, Mar 22 2018

Issue description

VULNERABILITY DETAILS
BoringSSL's and LibreSSL's X509_VERIFY_PARAM_set1_host() function behaves differently than OpenSSL's implementation in a rather subtle and hard to detect way. As a consequence, X509_VERIFY_PARAM_set1_host(param, "hostname", 0) does NOT validate the hostname against SAN fields with LibreSSL and BoringSSL. Under OpenSSL it works perfectly fine and correctly validates hostname against SAN/CN.

The function signature is

  int X509_VERIFY_PARAM_set1_host(X509_VERIFY_PARAM *param,
                                 const char *name, size_t namelen);

OpenSSL allows namelen == 0, which is equivalent to namelen == strlen(name) for NULL terminated strings. However LibreSSL and BoringSSL consider namelen == 0 like name == NULL. Both libraries clear the value of X509_VERIFY_PARAM_ID->host and return success (1). Both OpenSSL and LibreSSL 2.7.0 document contain "If name is NUL-terminated, namelen may be zero, otherwise namelen must be set to the length of name."

The bug is in line https://boringssl.googlesource.com/boringssl/+/master/crypto/x509/x509_vpm.c#103

I wrote this message to LibreSSL security team. Bob Beck replied that LibreSSL took the implementation from BoringSSL.

---
LibreSSL introduced X509_VERIFY_PARAM_set1_host() from OpenSSL 1.0.2.
The function sets the expected DNS hostname for a connection. During
cert chain validation, hostname is matched against subject alternative
name fields.

The implementation in LibreSSL 2.7.0 is broken. I have attached an
example program. With OpenSSL 1.1.0, the example fails with:

$ gcc client.c -lcrypto -lssl -o client && ./client Error connecting to
server
140315902109312:error:1416F086:SSL
routines:tls_process_server_certificate:certificate verify
failed:ssl/statem/statem_clnt.c:1230:
X509 verify error: Hostname mismatch

With LibreSSL 2.7.0 the example program doesn't refuse the peer's
certificate. It's a bug in LibreSSL's implementation of
X509_VERIFY_PARAM_set1_host() and int_x509_param_set_hosts() because
namelen == 0 is handled incorrectly. It's documented as "If name is
NUL-terminated, namelen may be zero, otherwise namelen must be set to
the length of name.". However the function stops early when namelen is
0. As consequence of the bug, X509_VERIFY_PARAM_ID's host value is never
set and the hostname is never verified during the handshake.

The attached patch fixes the issue for me. Please request a CVE for this
bug.
---

VERSION
All version of boringssl including git master.

REPRODUCTION CASE
See attachmen
 
client.c
2.4 KB View Download

Comment 1 by sleevi@google.com, Mar 22 2018

Cc: svaldez@chromium.org agl@chromium.org davidben@chromium.org
Components: Internals>Network>SSL
Project Member

Comment 2 by bugdroid1@chromium.org, Mar 22 2018

The following revision refers to this bug:
  https://boringssl.googlesource.com/boringssl/+/e759a9cd84198613199259dbed401f4951747cff

commit e759a9cd84198613199259dbed401f4951747cff
Author: Adam Langley <alangley@gmail.com>
Date: Thu Mar 22 17:19:07 2018

Support the OpenSSL “pass zero for strlen” when setting X.509 hostnames.

BoringSSL does not generally support this quirk but, in this case, we
didn't make it a fatal error and it's instead a silent omission of
hostname checking. This doesn't affect Chrome but, in case something is
using BoringSSL and using this trick, this change makes it safe.

BUG= chromium:824799 

Change-Id: If417817b997b9faa9963c09dfc95d06a5d445e0b
Reviewed-on: https://boringssl-review.googlesource.com/26724
Commit-Queue: Adam Langley <alangley@gmail.com>
Commit-Queue: David Benjamin <davidben@google.com>
Reviewed-by: David Benjamin <davidben@google.com>
CQ-Verified: CQ bot account: commit-bot@chromium.org <commit-bot@chromium.org>

[modify] https://crrev.com/e759a9cd84198613199259dbed401f4951747cff/crypto/x509/x509_vpm.c
[modify] https://crrev.com/e759a9cd84198613199259dbed401f4951747cff/crypto/x509/x509_test.cc

Comment 3 by agl@chromium.org, Mar 22 2018

Labels: reward-topanel
Status: Fixed (was: Unconfirmed)
Thank you for the report. We deliberately don't want to support magic behaviour in APIs like a length of zero not meaning zero. However, in this case a) we didn't make zero an error and b) using an empty string is dangerous.

While this doesn't affect Chrome, it's not the sort of robustness that we aim for. Had we made a zero length an error from the beginning, we could be sure that nothing was depending on this. However, since we screwed that up, the safest course, sadly, appears to be to support this magic in case people assume OpenSSL semantics.

Normally I would unrestrict this bug but you mentioned that Libre might be affected. I didn't know that they pulled from us but, in light of that, we'll let this bug follow the usual disclosure path and keep it limited for now.

While I suspect that, since this isn't an issue in Chrome, it wouldn't qualify under the VRP, I'll tag this anyway as I think it's a sound concern and not every security fix has to happen once the fire is burning.

Comment 4 by tira...@gmail.com, Mar 22 2018

Thanks Adam,

Bob Beck from LibreSSL security team told me that they are going to release a new version of LibreSSL very soon. Only LibreSSL 2.7.0 is affected. LibreSSL 2.6 and earlier didn't have the X509_VERIFY_PARAM_set1_host() API. Bob also told me that LibreSSL 2.7.0 qualifies as beta release. The latest stable is 2.6.4.

The feature was added after I complained (https://github.com/libressl-portable/portable/issues/381) that the lack of API is breaking new SSL module feature in upcoming Python 3.7.0 release. After all Python core devs agreed to break compatibility with OpenSSL 0.9.8 and 1.0.1, I replaced Python's custom hostname matching code with X509_VERIFY_PARAM_set1_host(). I got tired of all the security bugs in our code.

Anyway, I'll drop a note on this ticket as soon as LibreSSL 2.7.1 is out.

Comment 5 by tira...@gmail.com, Mar 24 2018

LibreSSL 2.7.1 is out. You can lift the restriction.
Project Member

Comment 6 by sheriffbot@chromium.org, Mar 24 2018

Labels: -Restrict-View-SecurityTeam Restrict-View-SecurityNotify

Comment 7 by tira...@gmail.com, Mar 25 2018

FYI, MITRE has assigned CVE-2018-8970 for the LibreSSL bug.

I haven't requested a CVE # for BoringSSL. I leave it to your discretion. By the way, the issue was noticed before. Bug report https://bugs.chromium.org/p/boringssl/issues/detail?id=30 not only complaints about lack of documentation but also about different behavior with namelen=0. Déjà vu!

Comment 8 by tira...@gmail.com, Mar 26 2018

Yesterday I recalled, why I used X509_VERIFY_PARAM_set1_host(param, hostname, 0) in CPython rather than X509_VERIFY_PARAM_set1_host(param, hostname, strlen(hostname)). OpenSSL's wiki entry for hostname validation https://wiki.openssl.org/index.php/Hostname_validation suggests 0 as namelen parameter.

The page is also the first Google hit for search phrases like "openssl check hostname" and "openssl validate hostname". I guess more projects are using 0 instead of strlen(hostname). A quick search revealed that Mongo DB's C driver has namelen=0, too.

Comment 9 by agl@chromium.org, Mar 26 2018

> By the way, the issue was noticed before.

Sigh. I think we were estimating that Chromium's certificate verifier would be ready much faster at that point in time.

> OpenSSL's wiki entry for hostname validation https://wiki.openssl.org/index.php/Hostname_validation suggests 0 as namelen parameter.

And suggests not checking any return value :(

Thanks. We'll seek to fix that too.

Comment 10 by agl@chromium.org, Mar 30 2018

To follow-up here:

https://boringssl.googlesource.com/boringssl/+/1902d818ac4fef9497dfe5d0ce6f2c99f585bdff has been landed which tightens a number of things, including making passing zero as a length an error, and a case that causes all future validations to fail in case (as was documented in the wiki) the result is ignored.

That change does other things too, see the description.

The [wiki page](https://wiki.openssl.org/index.php/Hostname_validation) has been updated to a) check the return value and b) not use the zero-length trick.

Comment 11 by agl@chromium.org, Apr 4 2018

Labels: -Restrict-View-SecurityNotify
Derestricting since this doesn't affect Chromium and LibreSSL have done a release.

Comment 12 by agl@chromium.org, Apr 4 2018

Labels: allpublic
(Trying again to derestrict.)
Labels: -reward-topanel reward-unpaid reward-500
*** Boilerplate reminders! ***
Please do NOT publicly disclose details until a fix has been released to all our users. Early public disclosure may cancel the provisional reward. Also, please be considerate about disclosure when the bug affects a core library that may be used by other products. Please do NOT share this information with third parties who are not directly involved in fixing the bug. Doing so may cancel the provisional reward. Please be honest if you have already disclosed anything publicly or to third parties. Lastly, we understand that some of you are not interested in money. We offer the option to donate your reward to an eligible charity. If you prefer this option, let us know and we will also match your donation - subject to our discretion. Any rewards that are unclaimed after 12 months will be donated to a charity of our choosing.
*********************************
Cc: tira...@gmail.com
Hi tiran79@gmail.com - the Chrome VRP panel decided to award $500 for this report. A member of our finance team will be in touch to arrange for payment. Cheers!
Labels: -reward-unpaid reward-inprocess
Labels: Security_Impact-Stable Security_Severity-Low
Labels: OS-Android OS-Chrome OS-Fuchsia OS-Linux OS-Mac OS-Windows
Project Member

Comment 18 by sheriffbot@chromium.org, Jul 28

Labels: Pri-2

Sign in to add a comment