Browse code

Don't assert out on receiving too-large control packets (CVE-2017-7478)

Commit 3c1b19e0 changed the maximum size of accepted control channel
packets. This was needed for crypto negotiation (which is needed for a
nice transition to a new default cipher), but exposed a DoS
vulnerability. The vulnerability was found during the OpenVPN 2.4 code
audit by Quarkslab (commisioned by OSTIF).

To fix the issue, we should not ASSERT() on external input (in this case
the received packet size), but instead gracefully error out and drop the
invalid packet.

CVE: 2017-7478
Signed-off-by: Steffan Karger <steffan.karger@fox-it.com>
Acked-by: David Sommerseth <davids@openvpn.net>
Message-Id: <1494358209-4568-2-git-send-email-steffan.karger@fox-it.com>
URL: http://www.mail-archive.com/search?l=mid&q=1494358209-4568-2-git-send-email-steffan.karger@fox-it.com
Signed-off-by: David Sommerseth <davids@openvpn.net>

Steffan Karger authored on 2017/05/10 04:30:08
Showing 2 changed files
... ...
@@ -327,3 +327,11 @@ Bugfixes
327 327
 --------
328 328
 - Fix memory leak introduced in 2.4.1: if --remote-cert-tls is used, we leaked
329 329
   some memory on each TLS (re)negotiation.
330
+
331
+Security
332
+--------
333
+- Fix a pre-authentication denial-of-service attack on both clients and servers.
334
+  By sending a too-large control packet, OpenVPN 2.4.0 or 2.4.1 can be forced
335
+  to hit an ASSERT() and stop the process.  If ``--tls-auth`` or ``--tls-crypt``
336
+  is used, only attackers that have the ``--tls-auth`` or ``--tls-crypt`` key
337
+  can mount an attack. (OSTIF/Quarkslab audit finding 5.1, CVE-2017-7478)
... ...
@@ -3720,7 +3720,12 @@ tls_pre_decrypt(struct tls_multi *multi,
3720 3720
                                 /* Save incoming ciphertext packet to reliable buffer */
3721 3721
                                 struct buffer *in = reliable_get_buf(ks->rec_reliable);
3722 3722
                                 ASSERT(in);
3723
-                                ASSERT(buf_copy(in, buf));
3723
+                                if(!buf_copy(in, buf))
3724
+                                {
3725
+                                    msg(D_MULTI_DROPPED,
3726
+                                        "Incoming control channel packet too big, dropping.");
3727
+                                    goto error;
3728
+                                }
3724 3729
                                 reliable_mark_active_incoming(ks->rec_reliable, in, id, op);
3725 3730
                             }
3726 3731