TIL: Some surprising code execution sources in bash
https://yossarian.net/til/post/some-surprising-code-execution-sources-in-bash
@yossarian The use of '[[' is the problem. That's an evaluating comparison and is as dangerous as 'eval' (as shown). All scripts should be using just the single '['. Using '[[' is for compatibility with ancient shells.
@kees this itself is a TIL for me, since I was taught/received that [[ is newer than [!
but also, is this always true? [ and ‘test’ will also use eval if the builtin version gets used first, but I don’t know the rules around when the builtins are used vs. not (for my interactive shell, they seem to always have precedence)
$ type [
[ is a shell builtin
$ foo='a[$(echo bad >&2)] + 7'
$ if [ "$foo" -eq 0 ]; then echo zero; fi
-bash: [: a[$(echo bad >&2)] + 7: integer expression expected
$ if /usr/bin/[ "$foo" -eq 0 ]; then echo zero; fi
/usr/bin/[: invalid integer ‘a[$(echo bad >&2)] + 7’
Both built-in and binary appear safe to me. The [[ remains unsafe:
$ if [[ "$foo" -eq 0 ]]; then echo zero; fi
bad
Dash and busybox are safe too:
dash: 3: [: Illegal number: a[$(echo bad >&2)] + 7
sh: a[$(echo bad >&2)] + 7: bad number
@kees out of curiosity, which version of bash was that? I got the [ and test variants working locally; I’ll find and share those tonight
@yossarian My bash is from Ubuntu 22.04:
GNU bash, version 5.1.16(1)-release (x86_64-pc-linux-gnu)
If you have a PoC working with [ I am excited to see it! I wonder if there is some distro shell patching going on...
here's a PoC for `test` and `[` working with the `-v` case:
```
# case 1
test -v 'x[$(cat /etc/passwd)]'
# case 2
[ -v 'x[$(cat /etc/passwd)]' ]
```
OTOH the arithmetic case doesn't work, and i get the same errors as you two:
```
$ test 'a[$(cat /etc/passwd > /tmp/pwned)]' -eq 0
bash: test: a[$(cat /etc/passwd > /tmp/pwned)]: integer expression expected
$ [ 'a[$(cat /etc/passwd > /tmp/pwned)]' -eq 0 ]
bash: [: a[$(cat /etc/passwd > /tmp/pwned)]: integer expression expected
```
...so my post is a little wrong, the "it works for [ and test" should be only under the `-v` case
Hah! Nice find. I didn't even know about "-v", and it seems to be a bashism (dash, busybox, and test all balk at it). I've always used "-z" for that kind of thing.
Looking at the bash manpage, it seems it's not everything that takes a "varname" (i.e. -R doesn't trip), just -v exposing the array parser again.