Eric Blake
2019-Sep-16 19:06 UTC
[Libguestfs] [LIBNBD SECURITY PATCH 0/1] NBD Protocol Downgrade Attack in libnbd
We discovered a possible Downgrade Attack in libnbd. Lifecycle --------- Reported: 2019-09-14 Fixed: 2019-09-16 Published: 2019-09-16 There is no CVE number assigned for this issue yet, but the bug is being categorized and processed by Red Hat's security team which may result in a CVE being published later. Description ----------- Libnbd includes the method nbd_set_tls(h, LIBNBD_TLS_REQUIRE) which is documented to let a client refuse to connect to a server that is not using TLS encryption. However, if the server uses the oldstyle protocol, a flaw in libnbd meant that the client would proceed with an unencrypted connection without warning. An attacker, perhaps acting as a man-in-the-middle, can proceed to offer the oldstyle protocol rather than the newstyle protocol in an effort to coerce the client to send plaintext data over the network that the client thought would be secured. Workarounds ----------- It is recommended to upgrade to a fixed version of libnbd (see next section). However if this cannot be done, it is possible for a client to test after connection whether the server also supports extension features that require the newstyle protocol, and thus be sure that an oldstyle server did not thwart encryption. Either of the following extension tests will prove that a newstyle server is present (unfortunately, this does not help for a newstyle server that does not support either extension): - If nbd_can_df(h) returns true. - If the client requests nbd_add_meta_context(h, context) prior to connection, then nbd_can_meta_context(h, context) returns true; the most commonly supported context is LIBNBD_CONTEXT_BASE_ALLOCATION. Test if libnbd is vulnerable ---------------------------- Run the following command (tested with nbdkit 1.12 or newer): $ nbdsh -c 'h.set_tls(nbd.TLS_REQUIRE)' \ -c 'h.connect_command(["nbdkit", "-o", "-s", "null"])' \ -c 'print(h.get_size())' If the command succeeds and prints 0, then libnbd is vulnerable. The correct behavior is to fail with an error that the connection was not possible due to the server lacking encryption support. Fixes ----- This affects all stable versions of libnbd. A fix is available for 1.0 and the current development version: * development branch (1.1) https://github.com/libguestfs/libnbd/commit/cca3b10fea96a349a9d718cc92f4216e44944216 or use libnbdkit >= 1.1.2 from http://download.libguestfs.org/libnbd/1.1-development/ * stable branch 1.0 https://github.com/libguestfs/libnbd/commit/19217810ce4467cc8b3671a2797e110b3e19e6c4 or use nbdkit >= 1.0.2 from http://download.libguestfs.org/libnbd/1.0-stable/ Credit ------ Discovered by Eric Blake <eblake@redhat.com> Eric Blake (1): security: states: Fail oldstyle servers when tls==2 generator/states-oldstyle.c | 10 ++++++++++ tests/oldstyle.c | 17 +++++++++++++++++ 2 files changed, 27 insertions(+) -- 2.21.0
Eric Blake
2019-Sep-16 19:06 UTC
[Libguestfs] [libnbd PATCH 1/1] security: states: Fail oldstyle servers when tls==2
This test succeeds, which is wrong: $ nbdsh -c 'h.set_tls(nbd.TLS_REQUIRE)' \ -c 'h.connect_command(["nbdkit", "-o", "-s", "null"])' \ -c 'print(h.get_size())' 0 Consider the case of a server that allows, but does not require, TLS encryption. A client that wants to only use the server if encrypted (as evidenced by the request for LIBNBD_TLS_REQUIRE) can be subjected to a protocol downgrade attack: a man-in-the-middle attacker can translate the original server's unencrypted newstyle offerings into an oldstyle server, such that the client is now unaware that it is sending plain-text rather than the desired encrypted session. Red Hat security will probably assign this a CVE, but we felt it reasonable to publish the fix now, in part due to the rarity of oldstyle servers these days. Workaround: if the server offers extensions that are only possible in newstyle connections, a client can check post-connection but before sending any read or write requests that any of those extensions are enabled, to ensure that a newstyle connection is in use (unfortunately, this doesn't help for all servers). Known witnesses: - if nbd_can_df(h) returns true - if the client requested nbd_add_meta_context(h, context) prior to connection, then after connection nbd_can_meta_context(h, context) returns true (the most common context is LIBNBD_CONTEXT_BASE_ALLOCATION) --- generator/states-oldstyle.c | 10 ++++++++++ tests/oldstyle.c | 17 +++++++++++++++++ 2 files changed, 27 insertions(+) diff --git a/generator/states-oldstyle.c b/generator/states-oldstyle.c index 668931b..1aff185 100644 --- a/generator/states-oldstyle.c +++ b/generator/states-oldstyle.c @@ -46,6 +46,16 @@ gflags = be16toh (h->sbuf.old_handshake.gflags); eflags = be16toh (h->sbuf.old_handshake.eflags); + /* Server is unable to upgrade to TLS. If h->tls is not require (2) + * then we can continue unencrypted. + */ + if (h->tls == 2) { + SET_NEXT_STATE (%.DEAD); + set_error (ENOTSUP, "handshake: server is oldstyle, " + "but handle TLS setting is require (2)"); + return 0; + } + h->gflags = gflags; debug (h, "gflags: 0x%" PRIx16, gflags); diff --git a/tests/oldstyle.c b/tests/oldstyle.c index 64862b7..c179c45 100644 --- a/tests/oldstyle.c +++ b/tests/oldstyle.c @@ -87,6 +87,23 @@ main (int argc, char *argv[]) progname = argv[0]; + /* Initial sanity check that we can't require TLS */ + nbd = nbd_create (); + if (nbd == NULL) { + fprintf (stderr, "%s\n", nbd_get_error ()); + exit (EXIT_FAILURE); + } + if (nbd_set_tls (nbd, LIBNBD_TLS_REQUIRE) == -1) { + fprintf (stderr, "%s\n", nbd_get_error ()); + exit (EXIT_FAILURE); + } + if (nbd_connect_command (nbd, args) != -1) { + fprintf (stderr, "%s\n", "expected failure"); + exit (EXIT_FAILURE); + } + nbd_close (nbd); + + /* Now for a working connection */ nbd = nbd_create (); if (nbd == NULL) { fprintf (stderr, "%s\n", nbd_get_error ()); -- 2.21.0
Eric Blake
2019-Sep-16 20:05 UTC
Re: [Libguestfs] [LIBNBD SECURITY PATCH 0/1] NBD Protocol Downgrade Attack in libnbd
On 9/16/19 2:06 PM, Eric Blake wrote:> We discovered a possible Downgrade Attack in libnbd. > > Lifecycle > --------- > > Reported: 2019-09-14 Fixed: 2019-09-16 Published: 2019-09-16 > > There is no CVE number assigned for this issue yet, but the bug is > being categorized and processed by Red Hat's security team which may > result in a CVE being published later.CVE-2019-14842 has now been assigned. -- Eric Blake, Principal Software Engineer Red Hat, Inc. +1-919-301-3226 Virtualization: qemu.org | libvirt.org
Possibly Parallel Threads
- [libnbd PATCH] states: Avoid magic number for h->tls
- [libnbd PATCH] api: Add set_handshake_flags for integration
- [PATCH libnbd 1/2] api: Add new API to read whether TLS was negotiated.
- Re: [libnbd PATCH] API: Add nbd_set_opt_mode to expose NEGOTIATING state
- [PATCH libnbd 2/2] api: New API for reading NBD protocol.