Headline
CVE-2016-10009: add a whitelist of paths from which ssh-agent will load (via · openbsd/src@9476ce1
Untrusted search path vulnerability in ssh-agent.c in ssh-agent in OpenSSH before 7.4 allows remote attackers to execute arbitrary local PKCS#11 modules by leveraging control over a forwarded agent-socket.
@@ -1,4 +1,4 @@ /* $OpenBSD: ssh-agent.c,v 1.214 2016/09/12 01:22:38 deraadt Exp $ */ /* $OpenBSD: ssh-agent.c,v 1.215 2016/11/30 03:07:37 djm Exp $ */ /* * Author: Tatu Ylonen [email protected] * Copyright © 1995 Tatu Ylonen [email protected], Espoo, Finland Expand Down Expand Up @@ -69,11 +69,16 @@ #include “misc.h” #include “digest.h” #include “ssherr.h” #include “match.h”
#ifdef ENABLE_PKCS11 #include “ssh-pkcs11.h” #endif
#ifndef DEFAULT_PKCS11_WHITELIST # define DEFAULT_PKCS11_WHITELIST “/usr/lib/*,/usr/local/lib/*” #endif
typedef enum { AUTH_UNUSED, AUTH_SOCKET, Expand Down Expand Up @@ -121,6 +126,9 @@ pid_t cleanup_pid = 0; char socket_name[PATH_MAX]; char socket_dir[PATH_MAX];
/* PKCS#11 path whitelist */ static char *pkcs11_whitelist;
/* locking */ #define LOCK_SIZE 32 #define LOCK_SALT_SIZE 16 Expand Down Expand Up @@ -724,7 +732,7 @@ no_identities(SocketEntry *e, u_int type) static void process_add_smartcard_key(SocketEntry *e) { char *provider = NULL, *pin; char *provider = NULL, *pin, canonical_provider[PATH_MAX]; int r, i, version, count = 0, success = 0, confirm = 0; u_int seconds; time_t death = 0; Expand Down Expand Up @@ -756,19 +764,30 @@ process_add_smartcard_key(SocketEntry *e) goto send; } } if (realpath(provider, canonical_provider) == NULL) { verbose(“failed PKCS#11 add of \"%.100s\": realpath: %s", provider, strerror(errno)); goto send; } if (match_pattern_list(canonical_provider, pkcs11_whitelist, 0) != 1) { verbose(“refusing PKCS#11 add of \"%.100s\": " “provider not whitelisted", canonical_provider); goto send; } debug(“%s: add %.100s", __func__, canonical_provider); if (lifetime && !death) death = monotime() + lifetime;
count = pkcs11_add_provider(provider, pin, &keys); count = pkcs11_add_provider(canonical_provider, pin, &keys); for (i = 0; i < count; i++) { k = keys[i]; version = k->type == KEY_RSA1 ? 1 : 2; tab = idtab_lookup(version); if (lookup_identity(k, version) == NULL) { id = xcalloc(1, sizeof(Identity)); id->key = k; id->provider = xstrdup(provider); id->comment = xstrdup(provider); /* XXX */ id->provider = xstrdup(canonical_provider); id->comment = xstrdup(canonical_provider); /* XXX */ id->death = death; id->confirm = confirm; TAILQ_INSERT_TAIL(&tab->idlist, id, next); Expand Down Expand Up @@ -1157,7 +1176,7 @@ usage(void) { fprintf(stderr, “usage: ssh-agent [-c | -s] [-Dd] [-a bind_address] [-E fingerprint_hash]\n” " [-t life] [command [arg …]]\n” " [-P pkcs11_whitelist] [-t life] [command [arg …]]\n” " ssh-agent [-c | -s] -k\n”); exit(1); } Expand Down Expand Up @@ -1191,7 +1210,7 @@ main(int ac, char **av) OpenSSL_add_all_algorithms(); #endif
while ((ch = getopt(ac, av, “cDdksE:a:t:”)) != -1) { while ((ch = getopt(ac, av, “cDdksE:a:P:t:”)) != -1) { switch (ch) { case 'E’: fingerprint_hash = ssh_digest_alg_by_name(optarg); Expand All @@ -1206,6 +1225,11 @@ main(int ac, char **av) case 'k’: k_flag++; break; case 'P’: if (pkcs11_whitelist != NULL) fatal("-P option already specified”); pkcs11_whitelist = xstrdup(optarg); break; case 's’: if (c_flag) usage(); Expand Down Expand Up @@ -1240,6 +1264,9 @@ main(int ac, char **av) if (ac > 0 && (c_flag || k_flag || s_flag || d_flag || D_flag)) usage();
if (pkcs11_whitelist == NULL) pkcs11_whitelist = xstrdup(DEFAULT_PKCS11_WHITELIST);
if (ac == 0 && !c_flag && !s_flag) { shell = getenv(“SHELL”); if (shell != NULL && (len = strlen(shell)) > 2 && Expand Down Expand Up @@ -1385,7 +1412,7 @@ main(int ac, char **av) signal(SIGTERM, cleanup_handler); nalloc = 0;
if (pledge("stdio cpath unix id proc exec", NULL) == -1) if (pledge("stdio rpath cpath unix id proc exec", NULL) == -1) fatal("%s: pledge: %s", __progname, strerror(errno));
while (1) { Expand Down
Related news
The PKCS#11 feature in ssh-agent in OpenSSH versions prior to 9.3p2 has an insufficiently trustworthy search path, leading to remote code execution if an agent is forwarded to an attacker-controlled system.