summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDarren Tucker <dtucker@zip.com.au>2016-07-15 13:32:45 +1000
committerColin Watson <cjwatson@debian.org>2016-07-22 13:58:37 +0100
commite5ef9d3942cebda819a6fd81647b51c8d87d23df (patch)
tree51e73ff68b275ee8f0555a4a9fb8b2b9ad1155f4
parent43a633de1cabe77e652125dac394a99ad9cac3b4 (diff)
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@ Origin: upstream, https://anongit.mindrot.org/openssh.git/commit/?id=9286875a73b2de7736b5e50692739d314cd8d9dc Bug-Debian: https://bugs.debian.org/831902 Last-Update: 2016-07-22 Patch-Name: CVE-2016-6210-1.patch
-rw-r--r--auth-passwd.c12
-rw-r--r--openbsd-compat/xcrypt.c34
2 files changed, 42 insertions, 4 deletions
diff --git a/auth-passwd.c b/auth-passwd.c
index 63ccf3cab..530b5d4f7 100644
--- a/auth-passwd.c
+++ b/auth-passwd.c
@@ -193,7 +193,7 @@ int
193sys_auth_passwd(Authctxt *authctxt, const char *password) 193sys_auth_passwd(Authctxt *authctxt, const char *password)
194{ 194{
195 struct passwd *pw = authctxt->pw; 195 struct passwd *pw = authctxt->pw;
196 char *encrypted_password; 196 char *encrypted_password, *salt = NULL;
197 197
198 /* Just use the supplied fake password if authctxt is invalid */ 198 /* Just use the supplied fake password if authctxt is invalid */
199 char *pw_password = authctxt->valid ? shadow_pw(pw) : pw->pw_passwd; 199 char *pw_password = authctxt->valid ? shadow_pw(pw) : pw->pw_passwd;
@@ -202,9 +202,13 @@ sys_auth_passwd(Authctxt *authctxt, const char *password)
202 if (strcmp(pw_password, "") == 0 && strcmp(password, "") == 0) 202 if (strcmp(pw_password, "") == 0 && strcmp(password, "") == 0)
203 return (1); 203 return (1);
204 204
205 /* Encrypt the candidate password using the proper salt. */ 205 /*
206 encrypted_password = xcrypt(password, 206 * Encrypt the candidate password using the proper salt, or pass a
207 (pw_password[0] && pw_password[1]) ? pw_password : "xx"); 207 * NULL and let xcrypt pick one.
208 */
209 if (authctxt->valid && pw_password[0] && pw_password[1])
210 salt = pw_password;
211 encrypted_password = xcrypt(password, salt);
208 212
209 /* 213 /*
210 * Authentication is accepted if the encrypted passwords 214 * Authentication is accepted if the encrypted passwords
diff --git a/openbsd-compat/xcrypt.c b/openbsd-compat/xcrypt.c
index 8577cbd8a..8913bb81a 100644
--- a/openbsd-compat/xcrypt.c
+++ b/openbsd-compat/xcrypt.c
@@ -25,6 +25,7 @@
25#include "includes.h" 25#include "includes.h"
26 26
27#include <sys/types.h> 27#include <sys/types.h>
28#include <string.h>
28#include <unistd.h> 29#include <unistd.h>
29#include <pwd.h> 30#include <pwd.h>
30 31
@@ -62,11 +63,44 @@
62# define crypt DES_crypt 63# define crypt DES_crypt
63# endif 64# endif
64 65
66/*
67 * Pick an appropriate password encryption type and salt for the running
68 * system.
69 */
70static const char *
71pick_salt(void)
72{
73 struct passwd *pw;
74 char *passwd, *p;
75 size_t typelen;
76 static char salt[32];
77
78 if (salt[0] != '\0')
79 return salt;
80 strlcpy(salt, "xx", sizeof(salt));
81 if ((pw = getpwuid(0)) == NULL)
82 return salt;
83 passwd = shadow_pw(pw);
84 if (passwd[0] != '$' || (p = strrchr(passwd + 1, '$')) == NULL)
85 return salt; /* no $, DES */
86 typelen = p - passwd + 1;
87 strlcpy(salt, passwd, MIN(typelen, sizeof(salt)));
88 explicit_bzero(passwd, strlen(passwd));
89 return salt;
90}
91
65char * 92char *
66xcrypt(const char *password, const char *salt) 93xcrypt(const char *password, const char *salt)
67{ 94{
68 char *crypted; 95 char *crypted;
69 96
97 /*
98 * If we don't have a salt we are encrypting a fake password for
99 * for timing purposes. Pick an appropriate salt.
100 */
101 if (salt == NULL)
102 salt = pick_salt();
103
70# ifdef HAVE_MD5_PASSWORDS 104# ifdef HAVE_MD5_PASSWORDS
71 if (is_md5_salt(salt)) 105 if (is_md5_salt(salt))
72 crypted = md5_crypt(password, salt); 106 crypted = md5_crypt(password, salt);