Skip to content

Commit

Permalink
Harden env var imports
Browse files Browse the repository at this point in the history
  • Loading branch information
krader1961 committed Dec 18, 2019
1 parent 5efb243 commit c7de8b6
Show file tree
Hide file tree
Showing 3 changed files with 50 additions and 12 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Expand Up @@ -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).

Expand Down
37 changes: 25 additions & 12 deletions src/cmd/ksh93/sh/arith.c
Expand Up @@ -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;
Expand Down
23 changes: 23 additions & 0 deletions src/cmd/ksh93/tests/subshell.sh
Expand Up @@ -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"

1 comment on commit c7de8b6

@hixio-mh
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Merge pull request

Please sign in to comment.