From 70499767e510cf02e6b6771c51c8720defe99c54 Mon Sep 17 00:00:00 2001 From: Fabrice Fontaine Date: Wed, 28 Oct 2020 09:26:58 +0100 Subject: [PATCH] package/libpam-tacplus: fix CVE-2020-27743 libtac in pam_tacplus through 1.5.1 lacks a check for a failure of RAND_bytes()/RAND_pseudo_bytes(). This could lead to use of a non-random/predictable session_id. Signed-off-by: Fabrice Fontaine Signed-off-by: Thomas Petazzoni --- ...failure-of-OpenSSL-RAND_pseudo_bytes.patch | 146 ++++++++++++++++++ package/libpam-tacplus/libpam-tacplus.mk | 3 + 2 files changed, 149 insertions(+) create mode 100644 package/libpam-tacplus/0005-Check-for-failure-of-OpenSSL-RAND_pseudo_bytes.patch diff --git a/package/libpam-tacplus/0005-Check-for-failure-of-OpenSSL-RAND_pseudo_bytes.patch b/package/libpam-tacplus/0005-Check-for-failure-of-OpenSSL-RAND_pseudo_bytes.patch new file mode 100644 index 0000000000..ba87ca5a19 --- /dev/null +++ b/package/libpam-tacplus/0005-Check-for-failure-of-OpenSSL-RAND_pseudo_bytes.patch @@ -0,0 +1,146 @@ +From c9bed7496e81e550ee22746f23bbb11be2e046ed Mon Sep 17 00:00:00 2001 +From: Duncan Eastoe +Date: Thu, 22 Oct 2020 19:18:27 +0100 +Subject: [PATCH] magic.c: check for failure of RAND_[pseudo_]bytes + +When magic() is implemented via libcrypto's RAND_bytes or +RAND_pseudo_bytes we should check for a failure and abort to +ensure we don't use a predictable session_id. + +This prevents (further) weakening* of the TACACS+ protocol +"encryption" since session_id is an input to the algorithm. + +*by modern standards TACACS+ is deemed "obfuscated" - RFC 8907. + +[Retrieved from: +https://github.com/kravietz/pam_tacplus/commit/468cc9d484364ecdc8bb245805f5c1fcb415fec9] +Signed-off-by: Fabrice Fontaine +--- + libtac/lib/magic.c | 26 +++++++++++++++++++++----- + pam_tacplus.c | 6 ++++++ + 2 files changed, 27 insertions(+), 5 deletions(-) + +diff --git a/libtac/lib/magic.c b/libtac/lib/magic.c +index e13a483..ae6b44f 100644 +--- a/libtac/lib/magic.c ++++ b/libtac/lib/magic.c +@@ -81,26 +81,42 @@ magic() + + #elif defined(HAVE_OPENSSL_RAND_H) && defined(HAVE_LIBCRYPTO) + ++#include + #include + + /* RAND_bytes is OpenSSL's classic function to obtain cryptographic strength pseudo-random bytes +- however, since the magic() function is used to generate TACACS+ session id rather than crypto keys +- we can use RAND_pseudo_bytes() which doesn't deplete the system's entropy pool ++ however, we can use RAND_pseudo_bytes() which doesn't deplete the system's entropy pool, so long ++ as it returns a "cryptographically strong" result - since session_id is an input to the TACACS+ ++ "encryption" ("obfuscation" by modern standards - RFC 8907) algorithm. + */ + + u_int32_t + magic() + { + u_int32_t num; ++ int ret; + + #ifdef HAVE_RAND_BYTES +- RAND_bytes((unsigned char *)&num, sizeof(num)); ++ ret = RAND_bytes((unsigned char *)&num, sizeof(num)); + #elif HAVE_RAND_PSEUDO_BYTES +- RAND_pseudo_bytes((unsigned char *)&num, sizeof(num)); ++ ret = RAND_pseudo_bytes((unsigned char *)&num, sizeof(num)); + #else + #error Neither RAND_bytes nor RAND_pseudo_bytes seems to be available + #endif +- return num; ++ ++ /* RAND_bytes success / RAND_pseudo_bytes "cryptographically strong" result */ ++ if (ret == 1) ++ return num; ++ ++ TACSYSLOG(LOG_CRIT,"%s: " ++#ifdef HAVE_RAND_BYTES ++ "RAND_bytes " ++#else ++ "RAND_pseudo_bytes " ++#endif ++ "failed; ret: %d err: %ld", __FUNCTION__, ret, ERR_get_error()); ++ ++ exit(1); + } + + #else +diff --git a/pam_tacplus.c b/pam_tacplus.c +index a0cb83d..4999ca9 100644 +--- a/pam_tacplus.c ++++ b/pam_tacplus.c +@@ -718,6 +718,12 @@ int pam_sm_acct_mgmt(pam_handle_t *pamh, int UNUSED(flags), int argc, + PAM_EXTERN + int pam_sm_open_session(pam_handle_t *pamh, int UNUSED(flags), int argc, + const char **argv) { ++ ++/* Task ID has no need to be cryptographically strong so we don't ++ * check for failures of the RAND functions. If they fail then we are ++ * as well sending the accounting request regardless of whether any value ++ * was written to task_id. ++ */ + #if defined(HAVE_OPENSSL_RAND_H) && defined(HAVE_LIBCRYPTO) + # if defined(HAVE_RAND_BYTES) + RAND_bytes((unsigned char *) &task_id, sizeof(task_id)); + +From bceaab0cd51a09b88f40f19da799ac7390264bf8 Mon Sep 17 00:00:00 2001 +From: Duncan Eastoe +Date: Fri, 23 Oct 2020 11:23:07 +0100 +Subject: [PATCH 2/2] pam_tacplus.c: Fallback to using PID as task ID + +If there is a failure obtaining a random task ID for the session +accounting request then fallback to using the PID, as this is unique +for the lifetime of the PAM application and therefore session. +--- + pam_tacplus.c | 16 ++++++++++++---- + 1 file changed, 12 insertions(+), 4 deletions(-) + +diff --git a/pam_tacplus.c b/pam_tacplus.c +index 4999ca9..b69e3d0 100644 +--- a/pam_tacplus.c ++++ b/pam_tacplus.c +@@ -100,8 +100,13 @@ int _pam_send_account(int tac_fd, int type, const char *user, char *tty, + } else if (type == TAC_PLUS_ACCT_FLAG_STOP) { + tac_add_attrib(&attr, "stop_time", buf); + } +- sprintf(buf, "%hu", task_id); ++ ++ if (task_id == 0) ++ snprintf(buf, sizeof(buf), "%d", getpid()); ++ else ++ snprintf(buf, sizeof(buf), "%hu", task_id); + tac_add_attrib(&attr, "task_id", buf); ++ + tac_add_attrib(&attr, "service", tac_service); + if (tac_protocol[0] != '\0') + tac_add_attrib(&attr, "protocol", tac_protocol); +@@ -720,9 +725,8 @@ int pam_sm_open_session(pam_handle_t *pamh, int UNUSED(flags), int argc, + const char **argv) { + + /* Task ID has no need to be cryptographically strong so we don't +- * check for failures of the RAND functions. If they fail then we are +- * as well sending the accounting request regardless of whether any value +- * was written to task_id. ++ * check for failures of the RAND functions. If we fail to get an ID we ++ * fallback to using our PID (in _pam_send_account). + */ + #if defined(HAVE_OPENSSL_RAND_H) && defined(HAVE_LIBCRYPTO) + # if defined(HAVE_RAND_BYTES) +@@ -734,6 +738,10 @@ int pam_sm_open_session(pam_handle_t *pamh, int UNUSED(flags), int argc, + task_id=(short int) magic(); + #endif + ++ if (task_id == 0) ++ syslog(LOG_INFO, "%s: failed to generate random task ID, " ++ "falling back to PID", __FUNCTION__); ++ + return _pam_account(pamh, argc, argv, TAC_PLUS_ACCT_FLAG_START, NULL); + } /* pam_sm_open_session */ + diff --git a/package/libpam-tacplus/libpam-tacplus.mk b/package/libpam-tacplus/libpam-tacplus.mk index fd2b4f9a30..86a5b1c461 100644 --- a/package/libpam-tacplus/libpam-tacplus.mk +++ b/package/libpam-tacplus/libpam-tacplus.mk @@ -17,4 +17,7 @@ LIBPAM_TACPLUS_INSTALL_STAGING = YES LIBPAM_TACPLUS_CONF_ENV = \ ax_cv_check_cflags___fstack_protector_all=$(if $(BR2_TOOLCHAIN_HAS_SSP),yes,no) +# 0005-Check-for-failure-of-OpenSSL-RAND_pseudo_bytes.patch +LIBPAM_TACPLUS_IGNORE_CVES += CVE-2020-27743 + $(eval $(autotools-package)) -- 2.30.2