From 70c2ac20bdce1481c6af2dae071aee7747d5417e Mon Sep 17 00:00:00 2001 From: Jakub Jelen Date: Mon, 25 Jul 2016 15:29:47 +0200 Subject: [PATCH] CVE-2016-6210 is fixed upstream --- openssh-7.2p2-user-enumeration.patch | 215 --------------------------- openssh.spec | 5 - 2 files changed, 220 deletions(-) delete mode 100644 openssh-7.2p2-user-enumeration.patch diff --git a/openssh-7.2p2-user-enumeration.patch b/openssh-7.2p2-user-enumeration.patch deleted file mode 100644 index 91ccccf..0000000 --- a/openssh-7.2p2-user-enumeration.patch +++ /dev/null @@ -1,215 +0,0 @@ -From 9286875a73b2de7736b5e50692739d314cd8d9dc Mon Sep 17 00:00:00 2001 -From: Darren Tucker -Date: Fri, 15 Jul 2016 13:32:45 +1000 -Subject: [PATCH] Determine appropriate salt for invalid users. - -When sshd is processing a non-PAM login for a non-existent user it uses -the string from the fakepw structure as the salt for crypt(3)ing the -password supplied by the client. That string has a Blowfish prefix, so on -systems that don't understand that crypt will fail fast due to an invalid -salt, and even on those that do it may have significantly different timing -from the hash methods used for real accounts (eg sha512). This allows -user enumeration by, eg, sending large password strings. This was noted -by EddieEzra.Harari at verint.com (CVE-2016-6210). - -To mitigate, use the same hash algorithm that root uses for hashing -passwords for users that do not exist on the system. ok djm@ ---- - auth-passwd.c | 12 ++++++++---- - openbsd-compat/xcrypt.c | 34 ++++++++++++++++++++++++++++++++++ - 2 files changed, 42 insertions(+), 4 deletions(-) - -diff --git a/auth-passwd.c b/auth-passwd.c -index 63ccf3c..530b5d4 100644 ---- a/auth-passwd.c -+++ b/auth-passwd.c -@@ -193,7 +193,7 @@ int - sys_auth_passwd(Authctxt *authctxt, const char *password) - { - struct passwd *pw = authctxt->pw; -- char *encrypted_password; -+ char *encrypted_password, *salt = NULL; - - /* Just use the supplied fake password if authctxt is invalid */ - char *pw_password = authctxt->valid ? shadow_pw(pw) : pw->pw_passwd; -@@ -202,9 +202,13 @@ sys_auth_passwd(Authctxt *authctxt, const char *password) - if (strcmp(pw_password, "") == 0 && strcmp(password, "") == 0) - return (1); - -- /* Encrypt the candidate password using the proper salt. */ -- encrypted_password = xcrypt(password, -- (pw_password[0] && pw_password[1]) ? pw_password : "xx"); -+ /* -+ * Encrypt the candidate password using the proper salt, or pass a -+ * NULL and let xcrypt pick one. -+ */ -+ if (authctxt->valid && pw_password[0] && pw_password[1]) -+ salt = pw_password; -+ encrypted_password = xcrypt(password, salt); - - /* - * Authentication is accepted if the encrypted passwords -diff --git a/openbsd-compat/xcrypt.c b/openbsd-compat/xcrypt.c -index 8577cbd..8913bb8 100644 ---- a/openbsd-compat/xcrypt.c -+++ b/openbsd-compat/xcrypt.c -@@ -25,6 +25,7 @@ - #include "includes.h" - - #include -+#include - #include - #include - -@@ -62,11 +63,44 @@ - # define crypt DES_crypt - # endif - -+/* -+ * Pick an appropriate password encryption type and salt for the running -+ * system. -+ */ -+static const char * -+pick_salt(void) -+{ -+ struct passwd *pw; -+ char *passwd, *p; -+ size_t typelen; -+ static char salt[32]; -+ -+ if (salt[0] != '\0') -+ return salt; -+ strlcpy(salt, "xx", sizeof(salt)); -+ if ((pw = getpwuid(0)) == NULL) -+ return salt; -+ passwd = shadow_pw(pw); -+ if (passwd[0] != '$' || (p = strrchr(passwd + 1, '$')) == NULL) -+ return salt; /* no $, DES */ -+ typelen = p - passwd + 1; -+ strlcpy(salt, passwd, MIN(typelen, sizeof(salt))); -+ explicit_bzero(passwd, strlen(passwd)); -+ return salt; -+} -+ - char * - xcrypt(const char *password, const char *salt) - { - char *crypted; - -+ /* -+ * If we don't have a salt we are encrypting a fake password for -+ * for timing purposes. Pick an appropriate salt. -+ */ -+ if (salt == NULL) -+ salt = pick_salt(); -+ - # ifdef HAVE_MD5_PASSWORDS - if (is_md5_salt(salt)) - crypted = md5_crypt(password, salt); - -From 283b97ff33ea2c641161950849931bd578de6946 Mon Sep 17 00:00:00 2001 -From: Darren Tucker -Date: Fri, 15 Jul 2016 13:49:44 +1000 -Subject: [PATCH] Mitigate timing of disallowed users PAM logins. - -When sshd decides to not allow a login (eg PermitRootLogin=no) and -it's using PAM, it sends a fake password to PAM so that the timing for -the failure is not noticeably different whether or not the password -is correct. This behaviour can be detected by sending a very long -password string which is slower to hash than the fake password. - -Mitigate by constructing an invalid password that is the same length -as the one from the client and thus takes the same time to hash. -Diff from djm@ ---- - auth-pam.c | 35 +++++++++++++++++++++++++++++++---- - 1 file changed, 31 insertions(+), 4 deletions(-) - -diff --git a/auth-pam.c b/auth-pam.c -index 451de78..465b5a7 100644 ---- a/auth-pam.c -+++ b/auth-pam.c -@@ -232,7 +232,6 @@ static int sshpam_account_status = -1; - static char **sshpam_env = NULL; - static Authctxt *sshpam_authctxt = NULL; - static const char *sshpam_password = NULL; --static char badpw[] = "\b\n\r\177INCORRECT"; - - /* Some PAM implementations don't implement this */ - #ifndef HAVE_PAM_GETENVLIST -@@ -795,12 +794,35 @@ sshpam_query(void *ctx, char **name, char **info, - return (-1); - } - -+/* -+ * Returns a junk password of identical length to that the user supplied. -+ * Used to mitigate timing attacks against crypt(3)/PAM stacks that -+ * vary processing time in proportion to password length. -+ */ -+static char * -+fake_password(const char *wire_password) -+{ -+ const char junk[] = "\b\n\r\177INCORRECT"; -+ char *ret = NULL; -+ size_t i, l = wire_password != NULL ? strlen(wire_password) : 0; -+ -+ if (l >= INT_MAX) -+ fatal("%s: password length too long: %zu", __func__, l); -+ -+ ret = malloc(l + 1); -+ for (i = 0; i < l; i++) -+ ret[i] = junk[i % (sizeof(junk) - 1)]; -+ ret[i] = '\0'; -+ return ret; -+} -+ - /* XXX - see also comment in auth-chall.c:verify_response */ - static int - sshpam_respond(void *ctx, u_int num, char **resp) - { - Buffer buffer; - struct pam_ctxt *ctxt = ctx; -+ char *fake; - - debug2("PAM: %s entering, %u responses", __func__, num); - switch (ctxt->pam_done) { -@@ -821,8 +843,11 @@ sshpam_respond(void *ctx, u_int num, char **resp) - (sshpam_authctxt->pw->pw_uid != 0 || - options.permit_root_login == PERMIT_YES)) - buffer_put_cstring(&buffer, *resp); -- else -- buffer_put_cstring(&buffer, badpw); -+ else { -+ fake = fake_password(*resp); -+ buffer_put_cstring(&buffer, fake); -+ free(fake); -+ } - if (ssh_msg_send(ctxt->pam_psock, PAM_AUTHTOK, &buffer) == -1) { - buffer_free(&buffer); - return (-1); -@@ -1166,6 +1191,7 @@ sshpam_auth_passwd(Authctxt *authctxt, const char *password) - { - int flags = (options.permit_empty_passwd == 0 ? - PAM_DISALLOW_NULL_AUTHTOK : 0); -+ char *fake = NULL; - - if (!options.use_pam || sshpam_handle == NULL) - fatal("PAM: %s called when PAM disabled or failed to " -@@ -1181,7 +1207,7 @@ sshpam_auth_passwd(Authctxt *authctxt, const char *password) - */ - if (!authctxt->valid || (authctxt->pw->pw_uid == 0 && - options.permit_root_login != PERMIT_YES)) -- sshpam_password = badpw; -+ sshpam_password = fake = fake_password(password); - - sshpam_err = pam_set_item(sshpam_handle, PAM_CONV, - (const void *)&passwd_conv); -@@ -1191,6 +1217,7 @@ sshpam_auth_passwd(Authctxt *authctxt, const char *password) - - sshpam_err = pam_authenticate(sshpam_handle, flags); - sshpam_password = NULL; -+ free(fake); - if (sshpam_err == PAM_SUCCESS && authctxt->valid) { - debug("PAM: password authentication accepted for %.100s", - authctxt->user); - diff --git a/openssh.spec b/openssh.spec index 6f72376..8607bcb 100644 --- a/openssh.spec +++ b/openssh.spec @@ -221,10 +221,6 @@ Patch939: openssh-7.2p2-s390-closefrom.patch # expose more information to PAM # https://github.com/openssh/openssh-portable/pull/47 Patch940: openssh-7.2p2-expose-pam.patch -# Prevent user enumeration via covert timing channel (#1357443) -# https://github.com/openssh/openssh-portable/commit/9286875a -# https://github.com/openssh/openssh-portable/commit/283b97ff -Patch941: openssh-7.2p2-user-enumeration.patch # Rework SELinux context handling with chroot (#1357860) Patch942: openssh-7.2p2-chroot-capabilities.patch @@ -460,7 +456,6 @@ popd %patch933 -p1 -b .fingerprint %patch939 -p1 -b .s390-dev %patch940 -p1 -b .expose-pam -%patch941 -p1 -b .user-enumeration %patch942 -p1 -b .chroot-cap %patch200 -p1 -b .audit