Michal Nowak
2018-08-26 43616c8731a48eff82ca79506d41e2b1e3f90baf
OpenSSH: fix CVE-2018-15473 (username enumeration)

Fix from OpenSSH 7.8p1 (https://www.openssh.com/releasenotes.html):
```
* sshd(8): add some countermeasures against timing attacks used for
account validation/enumeration. sshd will enforce a minimum time
or each failed authentication attempt consisting of a global 5ms
minimum plus an additional per-user 0-4ms delay derived from a
host secret.
```

Debian patch: https://sources.debian.org/patches/openssh/1:7.4p1-10+deb9u4/upstream-delay-bailout-for-invalid-authenticating-user.patch/

**Testing (exploit: https://www.exploit-db.com/exploits/45210/)**

Affected:
```
$ python 45210.py 192.168.1.12 root
[+] Valid username

$ python 45210.py 192.168.1.12 thisisinvalid
[*] Invalid username
```

Fixed:
```
$ python 45210.py 192.168.1.181 root
[+] Valid username

$ python 45210.py 192.168.1.181 thisisinvalid
[+] Valid username
```
1 files added
1 files modified
152 ■■■■■ changed files
components/network/openssh/Makefile 5 ●●●●● patch | view | raw | blame | history
components/network/openssh/patches/CVE-2018-15473.patch 147 ●●●●● patch | view | raw | blame | history
components/network/openssh/Makefile
@@ -20,12 +20,13 @@
#
# Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved.
# Copyright 2018 Till Wegmüller
# Copyright 2018 Michal Nowak
#
include ../../../make-rules/shared-macros.mk
COMPONENT_NAME=        openssh
COMPONENT_VERSION=    7.4p1
COMPONENT_REVISION=    3
COMPONENT_REVISION=    4
HUMAN_VERSION=        $(COMPONENT_VERSION)
COMPONENT_SRC=        $(COMPONENT_NAME)-$(COMPONENT_VERSION)
@@ -34,7 +35,7 @@
#   OpenSSH <x>.<y>.<z>p<n> => IPS <x>.<y>.<z>.<n>
IPS_COMPONENT_VERSION=    7.4.0.1
COMPONENT_PROJECT_URL=    http://www.openssh.org/
COMPONENT_PROJECT_URL=    https://www.openssh.org
COMPONENT_ARCHIVE=    $(COMPONENT_SRC).tar.gz
COMPONENT_ARCHIVE_HASH=    sha256:1b1fc4a14e2024293181924ed24872e6f2e06293f3e8926a376b8aec481f19d1
COMPONENT_ARCHIVE_URL=    http://mirror.yandex.ru/pub/OpenBSD/OpenSSH/portable/$(COMPONENT_ARCHIVE)
components/network/openssh/patches/CVE-2018-15473.patch
New file
@@ -0,0 +1,147 @@
From c4ca1497658e0508e8595ad74978c07bc92a18e3 Mon Sep 17 00:00:00 2001
From: "djm@openbsd.org" <djm@openbsd.org>
Date: Tue, 31 Jul 2018 03:10:27 +0000
Subject: upstream: delay bailout for invalid authenticating user
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
... until after the packet containing the request has been fully parsed.
Reported by Dariusz Tytko and Michał Sajdak; ok deraadt
OpenBSD-Commit-ID: b4891882fbe413f230fe8ac8a37349b03bd0b70d
Origin: backport, http://anongit.mindrot.org/openssh.git/commit/?id=74287f5df9966a0648b4a68417451dd18f079ab8
Bug-Debian: https://bugs.debian.org/906236
Last-Update: 2018-08-21
Patch-Name: upstream-delay-bailout-for-invalid-authenticating-user.patch
---
 auth2-gss.c           |  9 ++++++---
 auth2-hostbased.c     |  9 +++++----
 auth2-pubkey.c        | 22 ++++++++++++++--------
 3 files changed, 25 insertions(+), 15 deletions(-)
commit 2a406637f4bdc9ad0e6002cd69200a58c56fae79
Author: Sébastien Delafond <sdelafond@gmail.com>
Date:   Tue Aug 21 05:54:48 2018 +0200
    CVE-2018-15473
diff --git a/auth2-gss.c b/auth2-gss.c
index 3b5036d..460cf98 100644
--- a/auth2-gss.c
+++ b/auth2-gss.c
@@ -102,9 +102,6 @@ userauth_gssapi(Authctxt *authctxt)
     u_int len;
     u_char *doid = NULL;
-    if (!authctxt->valid || authctxt->user == NULL)
-        return (0);
-
     mechs = packet_get_int();
     if (mechs == 0) {
         debug("Mechanism negotiation is not supported");
@@ -135,6 +132,12 @@ userauth_gssapi(Authctxt *authctxt)
         return (0);
     }
+    if (!authctxt->valid || authctxt->user == NULL) {
+        debug2("%s: disabled because of invalid user", __func__);
+        free(doid);
+        return (0);
+    }
+
     if (GSS_ERROR(PRIVSEP(ssh_gssapi_server_ctx(&ctxt, &goid)))) {
         if (ctxt != NULL)
             ssh_gssapi_delete_ctx(&ctxt);
diff --git a/auth2-hostbased.c b/auth2-hostbased.c
index 1b3c3b2..2fa94d2 100644
--- a/auth2-hostbased.c
+++ b/auth2-hostbased.c
@@ -66,10 +66,6 @@ userauth_hostbased(Authctxt *authctxt)
     int pktype;
     int authenticated = 0;
-    if (!authctxt->valid) {
-        debug2("userauth_hostbased: disabled because of invalid user");
-        return 0;
-    }
     pkalg = packet_get_string(&alen);
     pkblob = packet_get_string(&blen);
     chost = packet_get_string(NULL);
@@ -115,6 +111,11 @@ userauth_hostbased(Authctxt *authctxt)
         goto done;
     }
+    if (!authctxt->valid || authctxt->user == NULL) {
+        debug2("%s: disabled because of invalid user", __func__);
+        goto done;
+    }
+
     service = datafellows & SSH_BUG_HBSERVICE ? "ssh-userauth" :
         authctxt->service;
     buffer_init(&b);
diff --git a/auth2-pubkey.c b/auth2-pubkey.c
index add7713..40aae5b 100644
--- a/auth2-pubkey.c
+++ b/auth2-pubkey.c
@@ -79,16 +79,12 @@ userauth_pubkey(Authctxt *authctxt)
 {
     Buffer b;
     Key *key = NULL;
-    char *pkalg, *userstyle, *fp = NULL;
-    u_char *pkblob, *sig;
+    char *pkalg = NULL, *userstyle = NULL, *fp = NULL;
+    u_char *pkblob = NULL, *sig = NULL;
     u_int alen, blen, slen;
     int have_sig, pktype;
     int authenticated = 0;
-    if (!authctxt->valid) {
-        debug2("%s: disabled because of invalid user", __func__);
-        return 0;
-    }
     have_sig = packet_get_char();
     if (datafellows & SSH_BUG_PKAUTH) {
         debug2("%s: SSH_BUG_PKAUTH", __func__);
@@ -149,6 +145,12 @@ userauth_pubkey(Authctxt *authctxt)
         } else {
             buffer_put_string(&b, session_id2, session_id2_len);
         }
+        if (!authctxt->valid || authctxt->user == NULL) {
+            debug2("%s: disabled because of invalid user",
+                __func__);
+            buffer_free(&b);
+            goto done;
+        }
         /* reconstruct packet */
         buffer_put_char(&b, SSH2_MSG_USERAUTH_REQUEST);
         xasprintf(&userstyle, "%s%s%s", authctxt->user,
@@ -184,12 +186,16 @@ userauth_pubkey(Authctxt *authctxt)
             key = NULL; /* Don't free below */
         }
         buffer_free(&b);
-        free(sig);
     } else {
         debug("%s: test whether pkalg/pkblob are acceptable for %s %s",
             __func__, sshkey_type(key), fp);
         packet_check_eom();
+        if (!authctxt->valid || authctxt->user == NULL) {
+            debug2("%s: disabled because of invalid user",
+                __func__);
+            goto done;
+        }
         /* XXX fake reply and always send PK_OK ? */
         /*
          * XXX this allows testing whether a user is allowed
@@ -216,6 +222,7 @@ done:
     free(pkalg);
     free(pkblob);
     free(fp);
+    free(sig);
     return authenticated;
 }