From 593a5a8b7f272c2488c8a800820ae990942946e7 Mon Sep 17 00:00:00 2001 From: Martijn Dekker Date: Thu, 21 May 2020 14:27:51 +0200 Subject: [PATCH] Patch vulnerability CVE-2019-14868 Certain environment variables were interpreted as arithmetic expressions on startup, leading to code injection. Ref.: https://bugzilla.redhat.com/show_bug.cgi?id=1757324 https://github.com/att/ast/commit/c7de8b641266bac7c77942239ac659edfee9ecd2 (cherry picked from commit ee6b001d0611ad2e00b6da2c2b42051995c0a678) --- NEWS | 4 +++ src/cmd/ksh93/sh/arith.c | 43 +++++++++++++++++++++----------- src/cmd/ksh93/tests/variables.sh | 24 ++++++++++++++++++ 3 files changed, 57 insertions(+), 14 deletions(-) diff --git a/NEWS b/NEWS index 8752db946..a962ec18c 100644 --- a/NEWS +++ b/NEWS @@ -10,6 +10,10 @@ Any uppercase BUG_* names are modernish shell bug IDs. '<#pattern'. The bug was caused by out-of-sync streams. Details and discussion: https://github.com/att/ast/issues/61 +- Patched code injection vulerability CVE-2019-14868. As a result, you can + no longer use expressions in imported numeric environment variables; only + integer literals are allowed. + 2020-05-20: - Fix BUG_ISSETLOOP. Expansions like ${var+set} remained static when used diff --git a/src/cmd/ksh93/sh/arith.c b/src/cmd/ksh93/sh/arith.c index b10594219..6361431b7 100644 --- a/src/cmd/ksh93/sh/arith.c +++ b/src/cmd/ksh93/sh/arith.c @@ -513,21 +513,36 @@ Sfdouble_t sh_strnum(register const char *str, char** ptr, int mode) char base=(shp->inarith?0:10), *last; if(*str==0) { - if(ptr) - *ptr = (char*)str; - return(0); + d = 0.0; + last = (char*)str; + } else { + errno = 0; + d = strtonll(str,&last,&base,-1); + if (*last && !shp->inarith && sh_isstate(SH_INIT)) { + /* This call is to handle "base#value" literals if we're importing untrusted env vars. */ + errno = 0; + d = strtonll(str, &last, NULL, -1); + } + + if(*last || errno) + { + if (sh_isstate(SH_INIT)) { + /* + * Initializing means importing untrusted env vars. The string does not appear to be + * a recognized numeric literal, so give up. We can't safely call strval(), because + * that allows arbitrary expressions, causing security vulnerability CVE-2019-14868. + */ + d = 0.0; + } else { + if(!last || *last!='.' || last[1]!='.') + d = strval(shp,str,&last,arith,mode); + if(!ptr && *last && mode>0) + errormsg(SH_DICT,ERROR_exit(1),e_lexbadchar,*last,str); + } + } else if (!d && *str=='-') { + d = -0.0; + } } - errno = 0; - d = strtonll(str,&last,&base,-1); - if(*last || errno) - { - if(!last || *last!='.' || last[1]!='.') - d = strval(shp,str,&last,arith,mode); - if(!ptr && *last && mode>0) - errormsg(SH_DICT,ERROR_exit(1),e_lexbadchar,*last,str); - } - else if (!d && *str=='-') - d = -0.0; if(ptr) *ptr = last; return(d); diff --git a/src/cmd/ksh93/tests/variables.sh b/src/cmd/ksh93/tests/variables.sh index 590e55ca4..a0db965e4 100755 --- a/src/cmd/ksh93/tests/variables.sh +++ b/src/cmd/ksh93/tests/variables.sh @@ -737,5 +737,29 @@ actual=$(_test_v var) actual=$(_test_v IFS) [[ "$actual" = "$expect" ]] || err_exit "[[ -v IFS ]] expansion fails in loops (expected '$expect', got '$actual')" +# ====== +# Verify that importing untrusted environment variables does not allow evaluating +# arbitrary expressions, but does recognize all integer literals recognized by ksh. + +expect=8 +actual=$(env SHLVL='7' "$SHELL" -c 'echo $SHLVL') +[[ $actual == $expect ]] || err_exit "decimal int literal not recognized (expected '$expect', got '$actual')" + +expect=14 +actual=$(env SHLVL='013' "$SHELL" -c 'echo $SHLVL') +[[ $actual == $expect ]] || err_exit "leading zeros int literal not recognized (expected '$expect', got '$actual')" + +expect=4 +actual=$(env SHLVL='2#11' "$SHELL" -c 'echo $SHLVL') +[[ $actual == $expect ]] || err_exit "base#value int literal not recognized (expected '$expect', got '$actual')" + +expect=12 +actual=$(env SHLVL='16#B' "$SHELL" -c 'echo $SHLVL') +[[ $actual == $expect ]] || err_exit "base#value int literal not recognized (expected '$expect', got '$actual')" + +expect=1 +actual=$(env SHLVL="2#11+x[\$(env echo Exploited vuln CVE-2019-14868 >&2)0]" "$SHELL" -c 'echo $SHLVL' 2>&1) +[[ $actual == $expect ]] || err_exit "expression allowed on env var import (expected '$expect', got '$actual')" + # ====== exit $((Errors<125?Errors:125))