Skip to content
Permalink
Browse files

Harden env var imports

  • Loading branch information
krader1961 committed Dec 13, 2019
1 parent 5efb243 commit c7de8b641266bac7c77942239ac659edfee9ecd2
Showing with 50 additions and 12 deletions.
  1. +2 −0 CHANGELOG.md
  2. +25 −12 src/cmd/ksh93/sh/arith.c
  3. +23 −0 src/cmd/ksh93/tests/subshell.sh
@@ -4,6 +4,8 @@

## Notable non-backward compatible changes

- You can no longer use arbitrary expressions in imported numeric env vars;
only integer literals are allowed.
- The `login` and `newgrp` special builtins have been removed. Use
`exec login` and `exec newgrp` instead (#1348).

@@ -567,19 +567,32 @@ Sfdouble_t sh_strnum(Shell_t *shp, const char *str, char **ptr, int mode) {
char *last;

if (*str == 0) {
if (ptr) *ptr = (char *)str;
return 0;
}
errno = 0;
d = number(str, &last, shp->inarith ? 0 : 10, NULL);
if (*last) {
if (*last != '.' || last[1] != '.') {
d = strval(shp, str, &last, arith, mode);
Varsubscript = true;
d = 0.0;
last = (char *)str;
} else {
d = number(str, &last, shp->inarith ? 0 : 10, NULL);
if (*last && !shp->inarith && sh_isstate(shp, SH_INIT)) {
// This call is to handle "base#value" literals if we're importing untrusted env vars.
d = number(str, &last, 0, NULL);
}
if (*last) {
if (sh_isstate(shp, SH_INIT)) {
// Initializing means importing untrusted env vars. Since the string does not appear
// to be a recognized numeric literal give up. We can't safely call strval() since
// that allows arbitrary expressions which would create a security vulnerability.
d = 0.0;
} else {
if (*last != '.' || last[1] != '.') {
d = strval(shp, str, &last, arith, mode);
Varsubscript = true;
}
if (!ptr && *last && mode > 0) {
errormsg(SH_DICT, ERROR_exit(1), e_lexbadchar, *last, str);
}
}
} else if (d == 0.0 && *str == '-') {
d = -0.0;
}
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;
@@ -856,3 +856,26 @@ for exp in 65535 65536
do got=$($SHELL -c 'x=$(printf "%.*c" '$exp' x); print ${#x}' 2>&1)
[[ $got == $exp ]] || log_error "large command substitution failed" "$exp" "$got"
done

# ==========
# Verify that importing untrusted env vars 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 ]] || log_error "decimal int literal not recognized" "$expect" "$actual"

expect=14
actual=$(env SHLVL='013' $SHELL -c 'echo $SHLVL')
[[ $actual == $expect ]] || log_error "leading zeros int literal not recognized" "$expect" "$actual"

expect=4
actual=$(env SHLVL='2#11' $SHELL -c 'echo $SHLVL')
[[ $actual == $expect ]] || log_error "base#value int literal not recognized" "$expect" "$actual"

expect=12
actual=$(env SHLVL='16#B' $SHELL -c 'echo $SHLVL')
[[ $actual == $expect ]] || log_error "base#value int literal not recognized" "$expect" "$actual"

expect=1
actual=$(env SHLVL="2#11+x[\$($bin_echo DANGER WILL ROBINSON >&2)0]" $SHELL -c 'echo $SHLVL')
[[ $actual == $expect ]] || log_error "expression allowed on env var import" "$expect" "$actual"

0 comments on commit c7de8b6

Please sign in to comment.
You can’t perform that action at this time.