Compare commits

...

8 Commits
master ... f23

Author SHA1 Message Date
Jakub Jelen
e7932f4770 openssh-7.2p2-6 + 0.10.2-3 2016-09-30 15:09:07 +02:00
Jakub Jelen
5f3ebc826d Fix NULL derefence (#1380297)
https://anongit.mindrot.org/openssh.git/patch/?id=28652bca29046f62c7045e933e6b931de1d16737
2016-09-30 15:05:38 +02:00
Jakub Jelen
986af88658 openssh-7.2p2-5 + 0.10.2-3 2016-07-27 12:38:04 +02:00
Jakub Jelen
5d464e8b62 Rework SELinux context handling with chroot using libcap-ng (#1357860) 2016-07-27 12:36:03 +02:00
Jakub Jelen
2762c74636 openssh-7.2p2-4 + 0.10.2-3 2016-07-18 15:06:46 +02:00
Jakub Jelen
920d3a7915 Prevent user enumeration via timing channel (CVE-2016-6210) 2016-07-18 15:01:32 +02:00
Jakub Jelen
cb306d6a7c openssh-7.2p2-3 + 0.10.2-3 2016-04-22 15:23:05 +02:00
Jakub Jelen
669db41533 Fix for CVE-2015-8325 (#1328013) 2016-04-22 15:20:11 +02:00
5 changed files with 425 additions and 1 deletions

View File

@ -0,0 +1,32 @@
From 85bdcd7c92fe7ff133bbc4e10a65c91810f88755 Mon Sep 17 00:00:00 2001
From: Damien Miller <djm@mindrot.org>
Date: Wed, 13 Apr 2016 10:39:57 +1000
Subject: ignore PAM environment vars when UseLogin=yes
If PAM is configured to read user-specified environment variables
and UseLogin=yes in sshd_config, then a hostile local user may
attack /bin/login via LD_PRELOAD or similar environment variables
set via PAM.
CVE-2015-8325, found by Shayan Sadigh, via Colin Watson
---
session.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/session.c b/session.c
index 4859245..4653b09 100644
--- a/session.c
+++ b/session.c
@@ -1322,7 +1322,7 @@ do_setup_env(Session *s, const char *shell)
* Pull in any environment variables that may have
* been set by PAM.
*/
- if (options.use_pam) {
+ if (options.use_pam && !options.use_login) {
char **p;
p = fetch_pam_child_environment();
--
cgit v0.11.2

View File

@ -0,0 +1,102 @@
diff --git a/configure.ac b/configure.ac
index aeef42a..d01e67e 100644
--- a/configure.ac
+++ b/configure.ac
@@ -4998,6 +4998,37 @@ if test -n "$conf_lastlog_location"; then
[Define if you want to specify the path to your lastlog file])
fi
+AC_ARG_WITH(libcap-ng,
+ [ --with-libcap-ng=[auto/yes/no] Add Libcap-ng support [default=auto]],,
+ with_libcap_ng=auto)
+
+dnl libcap-ng detection
+if test x$with_libcap_ng = xno ; then
+ have_libcap_ng=no;
+else
+ # Start by checking for header file
+ AC_CHECK_HEADER(cap-ng.h, capng_headers=yes, capng_headers=no)
+
+ # See if we have libcap-ng library
+ AC_CHECK_LIB(cap-ng, capng_clear, CAPNG_LDADD=-lcap-ng,)
+
+ # Check results are usable
+ if test x$with_libcap_ng = xyes -a x$CAPNG_LDADD = x ; then
+ AC_MSG_ERROR(libcap-ng support was requested and the library was not found)
+ fi
+ if test x$CAPNG_LDADD != x -a $capng_headers = no ; then
+ AC_MSG_ERROR(libcap-ng libraries found but headers are missing)
+ fi
+fi
+AC_MSG_CHECKING(whether to use libcap-ng)
+if test x$CAPNG_LDADD != x ; then
+ AC_DEFINE(HAVE_LIBCAP_NG,1,[libcap-ng support])
+ SSHDLIBS="$SSHDLIBS -lcap-ng"
+ AC_MSG_RESULT(yes)
+else
+ AC_MSG_RESULT(no)
+fi
+
dnl utmp detection
AC_MSG_CHECKING([if your system defines UTMP_FILE])
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
diff --git a/session.c b/session.c
index 6cfcba4..80d2806 100644
--- a/session.c
+++ b/session.c
@@ -96,6 +96,10 @@
#include "monitor_wrap.h"
#include "sftp.h"
+#ifdef HAVE_LIBCAP_NG
+#include <cap-ng.h>
+#endif
+
#if defined(KRB5) && defined(USE_AFS)
#include <kafs.h>
#endif
@@ -1586,6 +1590,7 @@ void
do_setusercontext(struct passwd *pw)
{
char *chroot_path, *tmp;
+ int dropped_suid = -1;
platform_setusercontext(pw);
@@ -1619,10 +1624,24 @@ do_setusercontext(struct passwd *pw)
pw->pw_uid);
chroot_path = percent_expand(tmp, "h", pw->pw_dir,
"u", pw->pw_name, (char *)NULL);
+#ifdef HAVE_LIBCAP_NG
+ /* drop suid soon, retain SYS_CHROOT capability */
+ capng_clear(CAPNG_SELECT_BOTH);
+ capng_update(CAPNG_ADD, CAPNG_EFFECTIVE|CAPNG_PERMITTED, CAP_SYS_CHROOT);
+ if ((dropped_suid = capng_change_id(pw->pw_uid, pw->pw_gid, CAPNG_DROP_SUPP_GRP | CAPNG_CLEAR_BOUNDING)) != 0)
+ logit("capng_change_id() = %d (failure): Try to drop UID later", dropped_suid);
+#endif
#ifdef WITH_SELINUX
sshd_selinux_copy_context();
#endif
safely_chroot(chroot_path, pw->pw_uid);
+#ifdef HAVE_LIBCAP_NG
+ /* Drop chroot capability. Already used */
+ if (dropped_suid == 0) {
+ capng_clear(CAPNG_SELECT_BOTH);
+ capng_apply(CAPNG_SELECT_BOTH);
+ }
+#endif
free(tmp);
free(chroot_path);
/* Make sure we don't attempt to chroot again */
@@ -1654,8 +1673,9 @@ do_setusercontext(struct passwd *pw)
if (!in_chroot && set_id(pw->pw_name) != 0)
fatal("set_id(%s) Failed", pw->pw_name);
# endif /* USE_LIBIAF */
- /* Permanently switch to the desired uid. */
- permanently_set_uid(pw);
+ /* Permanently switch to the desired uid if not yet done. */
+ if (dropped_suid != 0)
+ permanently_set_uid(pw);
#endif
#ifdef WITH_SELINUX

View File

@ -0,0 +1,215 @@
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@
---
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 <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);
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@
---
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);

View File

@ -0,0 +1,48 @@
From 28652bca29046f62c7045e933e6b931de1d16737 Mon Sep 17 00:00:00 2001
From: "markus@openbsd.org" <markus@openbsd.org>
Date: Mon, 19 Sep 2016 19:02:19 +0000
Subject: upstream commit
move inbound NEWKEYS handling to kex layer; otherwise
early NEWKEYS causes NULL deref; found by Robert Swiecki/honggfuzz; fixed
with & ok djm@
Upstream-ID: 9a68b882892e9f51dc7bfa9f5a423858af358b2f
---
kex.c | 4 +++-
packet.c | 6 ++----
2 files changed, 5 insertions(+), 5 deletions(-)
diff --git a/kex.c b/kex.c
index f4c130f..8800d40 100644
--- a/kex.c
+++ b/kex.c
@@ -425,6 +425,8 @@ kex_input_newkeys(int type, u_int32_t seq, void *ctxt)
ssh_dispatch_set(ssh, SSH2_MSG_NEWKEYS, &kex_protocol_error);
if ((r = sshpkt_get_end(ssh)) != 0)
return r;
+ if ((r = ssh_set_newkeys(ssh, MODE_IN)) != 0)
+ return r;
kex->done = 1;
sshbuf_reset(kex->peer);
/* sshbuf_reset(kex->my); */
diff --git a/packet.c b/packet.c
index 711091d..fb316ac 100644
--- a/packet.c
+++ b/packet.c
@@ -1907,9 +1907,7 @@ ssh_packet_read_poll2(struct ssh *ssh, u_char *typep, u_int32_t *seqnr_p)
return r;
return SSH_ERR_PROTOCOL_ERROR;
}
- if (*typep == SSH2_MSG_NEWKEYS)
- r = ssh_set_newkeys(ssh, MODE_IN);
- else if (*typep == SSH2_MSG_USERAUTH_SUCCESS && !state->server_side)
+ if (*typep == SSH2_MSG_USERAUTH_SUCCESS && !state->server_side)
r = ssh_packet_enable_delayed_compress(ssh);
else
r = 0;
--
cgit v0.12
0

View File

@ -66,7 +66,7 @@
# Do not forget to bump pam_ssh_agent_auth release if you rewind the main package release to 1 # Do not forget to bump pam_ssh_agent_auth release if you rewind the main package release to 1
%global openssh_ver 7.2p2 %global openssh_ver 7.2p2
%global openssh_rel 2 %global openssh_rel 6
%global pam_ssh_agent_ver 0.10.2 %global pam_ssh_agent_ver 0.10.2
%global pam_ssh_agent_rel 3 %global pam_ssh_agent_rel 3
@ -228,6 +228,16 @@ Patch933: openssh-7.0p1-show-more-fingerprints.patch
# Preserve IUTF8 tty mode flag over ssh connections (#1270248) # Preserve IUTF8 tty mode flag over ssh connections (#1270248)
# https://bugzilla.mindrot.org/show_bug.cgi?id=2477 # https://bugzilla.mindrot.org/show_bug.cgi?id=2477
Patch936: openssh-7.1p1-iutf8.patch Patch936: openssh-7.1p1-iutf8.patch
# CVE-2015-8325: ignore PAM environment vars when UseLogin=yes
Patch937: openssh-7.2p2-CVE-2015-8325.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
# Null dereference in newkeys code (#1380297)
Patch943: openssh-7.3p1-null-deref.patch
License: BSD License: BSD
@ -257,6 +267,7 @@ BuildRequires: tcp_wrappers-devel
BuildRequires: fipscheck-devel >= 1.3.0 BuildRequires: fipscheck-devel >= 1.3.0
BuildRequires: openssl-devel >= 0.9.8j BuildRequires: openssl-devel >= 0.9.8j
BuildRequires: perl-podlators BuildRequires: perl-podlators
BuildRequires: libcap-ng-devel
%if %{kerberos5} %if %{kerberos5}
BuildRequires: krb5-devel BuildRequires: krb5-devel
@ -462,6 +473,10 @@ popd
%patch932 -p1 -b .gsskexalg %patch932 -p1 -b .gsskexalg
%patch933 -p1 -b .fingerprint %patch933 -p1 -b .fingerprint
%patch936 -p1 -b .iutf8 %patch936 -p1 -b .iutf8
%patch937 -p1 -b .pam_uselogin_cve
%patch941 -p1 -b .user-enumeration
%patch942 -p1 -b .chroot-cap
%patch943 -p1 -b .deref
%patch200 -p1 -b .audit %patch200 -p1 -b .audit
%patch201 -p1 -b .audit-race %patch201 -p1 -b .audit-race
@ -809,6 +824,18 @@ getent passwd sshd >/dev/null || \
%endif %endif
%changelog %changelog
* Fri Sep 30 2016 Jakub Jelen <jjelen@redhat.com> - 7.2p2-6 + 0.10.2-3
- Fix NULL dereference (#1380297)
* Wed Jul 27 2016 Jakub Jelen <jjelen@redhat.com> - 7.2p2-5 + 0.10.2-3
- Prevent guest_t from running sudo (#1357860)
* Mon Jul 18 2016 Jakub Jelen <jjelen@redhat.com> - 7.2p2-4 + 0.10.2-3
- CVE-2016-6210: User enumeration via covert timing channel (#1357443)
* Fri Apr 22 2016 Jakub Jelen <jjelen@redhat.com> - 7.2p2-3 + 0.10.2-3
- CVE-2015-8325: ignore PAM environment vars when UseLogin=yes (#1328013)
* Wed Apr 06 2016 Jakub Jelen <jjelen@redhat.com> 7.2p2-2 + 0.10.2-3 * Wed Apr 06 2016 Jakub Jelen <jjelen@redhat.com> 7.2p2-2 + 0.10.2-3
- Fix GSSAPI Key Exchange according to RFC (#1323622) - Fix GSSAPI Key Exchange according to RFC (#1323622)
- Remove init.d/functions dependency from sshd-keygen (#1317722) - Remove init.d/functions dependency from sshd-keygen (#1317722)