summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorArmin Kuster <akuster@mvista.com>2016-09-17 20:58:40 -0700
committerRichard Purdie <richard.purdie@linuxfoundation.org>2016-09-23 23:21:43 +0100
commit7d07de3841c0a736262088c95a938deff194d9e2 (patch)
tree58d3d27e722eff7430cc05c1e8bee84fb067b46e
parent64ff6226d0c927c05fc42fd9ca8b31bac129b16d (diff)
downloadopenembedded-core-7d07de3841c0a736262088c95a938deff194d9e2.tar.gz
openembedded-core-7d07de3841c0a736262088c95a938deff194d9e2.tar.bz2
openembedded-core-7d07de3841c0a736262088c95a938deff194d9e2.zip
openssh: Security fix CVE-2016-6210
affects openssh < 7.3 Signed-off-by: Armin Kuster <akuster@mvista.com>
-rw-r--r--meta/recipes-connectivity/openssh/openssh/CVE-2016-6210.patch114
-rw-r--r--meta/recipes-connectivity/openssh/openssh/CVE-2016-6210_p2.patch110
-rw-r--r--meta/recipes-connectivity/openssh/openssh/CVE-2016-6210_p3.patch62
-rw-r--r--meta/recipes-connectivity/openssh/openssh_7.1p2.bb3
4 files changed, 289 insertions, 0 deletions
diff --git a/meta/recipes-connectivity/openssh/openssh/CVE-2016-6210.patch b/meta/recipes-connectivity/openssh/openssh/CVE-2016-6210.patch
new file mode 100644
index 0000000000..e3072b43f5
--- /dev/null
+++ b/meta/recipes-connectivity/openssh/openssh/CVE-2016-6210.patch
@@ -0,0 +1,114 @@
+From 9286875a73b2de7736b5e50692739d314cd8d9dc Mon Sep 17 00:00:00 2001
+From: Darren Tucker <dtucker@zip.com.au>
+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@
+
+Upstream-Status: Backport
+OpenSSH < 7.3
+CVE: CVE-2016-6210 patch1
+Signed-off-by: Armin Kuster <akuster@mvista.com>
+
+---
+ auth-passwd.c | 12 ++++++++----
+ openbsd-compat/xcrypt.c | 34 ++++++++++++++++++++++++++++++++++
+ 2 files changed, 42 insertions(+), 4 deletions(-)
+
+Index: openssh-7.1p2/auth-passwd.c
+===================================================================
+--- openssh-7.1p2.orig/auth-passwd.c
++++ openssh-7.1p2/auth-passwd.c
+@@ -198,7 +198,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;
+@@ -207,9 +207,13 @@ sys_auth_passwd(Authctxt *authctxt, cons
+ 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
+Index: openssh-7.1p2/openbsd-compat/xcrypt.c
+===================================================================
+--- openssh-7.1p2.orig/openbsd-compat/xcrypt.c
++++ openssh-7.1p2/openbsd-compat/xcrypt.c
+@@ -25,6 +25,7 @@
+ #include "includes.h"
+
+ #include <sys/types.h>
++#include <string.h>
+ #include <unistd.h>
+ #include <pwd.h>
+
+@@ -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);
diff --git a/meta/recipes-connectivity/openssh/openssh/CVE-2016-6210_p2.patch b/meta/recipes-connectivity/openssh/openssh/CVE-2016-6210_p2.patch
new file mode 100644
index 0000000000..f27c74c7c1
--- /dev/null
+++ b/meta/recipes-connectivity/openssh/openssh/CVE-2016-6210_p2.patch
@@ -0,0 +1,110 @@
+From 283b97ff33ea2c641161950849931bd578de6946 Mon Sep 17 00:00:00 2001
+From: Darren Tucker <dtucker@zip.com.au>
+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@
+
+Upstream-Status: Backport
+CVE: CVE-2016-6210 patch2
+Signed-off-by: Armin Kuster <akuster@mvista.com>
+
+---
+ auth-pam.c | 35 +++++++++++++++++++++++++++++++----
+ 1 file changed, 31 insertions(+), 4 deletions(-)
+
+Index: openssh-7.1p2/auth-pam.c
+===================================================================
+--- openssh-7.1p2.orig/auth-pam.c
++++ openssh-7.1p2/auth-pam.c
+@@ -231,7 +231,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
+@@ -809,12 +808,35 @@ sshpam_query(void *ctx, char **name, cha
+ 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) {
+@@ -835,8 +857,11 @@ sshpam_respond(void *ctx, u_int num, cha
+ (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);
+@@ -1180,6 +1205,7 @@ sshpam_auth_passwd(Authctxt *authctxt, c
+ {
+ 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 "
+@@ -1195,7 +1221,7 @@ sshpam_auth_passwd(Authctxt *authctxt, c
+ */
+ 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);
+@@ -1205,6 +1231,7 @@ sshpam_auth_passwd(Authctxt *authctxt, c
+
+ 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/meta/recipes-connectivity/openssh/openssh/CVE-2016-6210_p3.patch b/meta/recipes-connectivity/openssh/openssh/CVE-2016-6210_p3.patch
new file mode 100644
index 0000000000..790ec808be
--- /dev/null
+++ b/meta/recipes-connectivity/openssh/openssh/CVE-2016-6210_p3.patch
@@ -0,0 +1,62 @@
+From dbf788b4d9d9490a5fff08a7b09888272bb10fcc Mon Sep 17 00:00:00 2001
+From: Darren Tucker <dtucker@zip.com.au>
+Date: Thu, 21 Jul 2016 14:17:31 +1000
+Subject: [PATCH] Search users for one with a valid salt.
+
+If the root account is locked (eg password "!!" or "*LK*") keep looking
+until we find a user with a valid salt to use for crypting passwords of
+invalid users. ok djm@
+
+Upstream-Status: Backport
+CVE: CVE-2016-6210
+Signed-off-by: Armin Kuster <akuster@mvista.com>
+
+---
+ openbsd-compat/xcrypt.c | 24 +++++++++++++++---------
+ 1 file changed, 15 insertions(+), 9 deletions(-)
+
+diff --git a/openbsd-compat/xcrypt.c b/openbsd-compat/xcrypt.c
+index 8913bb8..cf6a9b9 100644
+--- a/openbsd-compat/xcrypt.c
++++ b/openbsd-compat/xcrypt.c
+@@ -65,7 +65,9 @@
+
+ /*
+ * Pick an appropriate password encryption type and salt for the running
+- * system.
++ * system by searching through accounts until we find one that has a valid
++ * salt. Usually this will be root unless the root account is locked out.
++ * If we don't find one we return a traditional DES-based salt.
+ */
+ static const char *
+ pick_salt(void)
+@@ -78,14 +80,18 @@ pick_salt(void)
+ 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));
++ setpwent();
++ while ((pw = getpwent()) != NULL) {
++ passwd = shadow_pw(pw);
++ if (passwd[0] == '$' && (p = strrchr(passwd+1, '$')) != NULL) {
++ typelen = p - passwd + 1;
++ strlcpy(salt, passwd, MIN(typelen, sizeof(salt)));
++ explicit_bzero(passwd, strlen(passwd));
++ goto out;
++ }
++ }
++ out:
++ endpwent();
+ return salt;
+ }
+
+--
+2.7.4
+
diff --git a/meta/recipes-connectivity/openssh/openssh_7.1p2.bb b/meta/recipes-connectivity/openssh/openssh_7.1p2.bb
index 56a1c8329a..bd047b0773 100644
--- a/meta/recipes-connectivity/openssh/openssh_7.1p2.bb
+++ b/meta/recipes-connectivity/openssh/openssh_7.1p2.bb
@@ -25,6 +25,9 @@ SRC_URI = "ftp://ftp.openbsd.org/pub/OpenBSD/OpenSSH/portable/openssh-${PV}.tar.
file://CVE-2016-1907_2.patch \
file://CVE-2016-1907_3.patch \
file://CVE-2016-3115.patch \
+ file://CVE-2016-6210.patch \
+ file://CVE-2016-6210_p2.patch \
+ file://CVE-2016-6210_p3.patch \
"
PAM_SRC_URI = "file://sshd"