Sign Up
Log In
Log In
or
Sign Up
Places
All Projects
Status Monitor
Collapse sidebar
SUSE:SLE-12-SP4:Update
openssh-testuser.26950
openssh-7.2p2-prevent_timing_user_enumeration.p...
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
File openssh-7.2p2-prevent_timing_user_enumeration.patch of Package openssh-testuser.26950
From 8630843eb7bade3acb5f549ba07e80d352c80950 Mon Sep 17 00:00:00 2001 From: Old openssh patches <pcerny@suse.com> Date: Wed, 26 Oct 2022 09:54:29 +0200 Subject: [PATCH] openssh-7.2p2-prevent_timing_user_enumeration # HG changeset patch # Parent 40ce0de74a0d8b8181862b237b693d938310527b Prevent user enumeration through password processing timing CVE-2016-6210 bsc#989363 non-PAM part: upstream commit: 9286875a73b2de7736b5e50692739d314cd8d9dc PAM part: upstream commit: 283b97ff33ea2c641161950849931bd578de6946 --- auth-pam.c | 35 +++++++++++++++++++++++++++++++---- auth-passwd.c | 12 ++++++++---- openbsd-compat/xcrypt.c | 34 ++++++++++++++++++++++++++++++++++ 3 files changed, 73 insertions(+), 8 deletions(-) diff --git a/auth-pam.c b/auth-pam.c index d436155a..c3a6b61c 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 @@ -812,12 +811,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 = xmalloc(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) { @@ -838,8 +860,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); @@ -1183,6 +1208,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 " @@ -1198,7 +1224,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); @@ -1208,6 +1234,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/auth-passwd.c b/auth-passwd.c index 63ccf3ca..530b5d4f 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 8577cbd8..8913bb81 100644 --- a/openbsd-compat/xcrypt.c +++ b/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); -- 2.38.0
Locations
Projects
Search
Status Monitor
Help
OpenBuildService.org
Documentation
API Documentation
Code of Conduct
Contact
Support
@OBShq
Terms
openSUSE Build Service is sponsored by
The Open Build Service is an
openSUSE project
.
Sign Up
Log In
Places
Places
All Projects
Status Monitor