Rule of thumb: quote all your variables.
Rule of thumb: quote all your variables.
It's unfortunate the semantics of bash don't have variable references behave like they are quoted by default. I really wish it did.
#!/bin/bash
items=(
'a'
'b c'
"d\te"
"f\ng"
)
echo "Unquoted:"
for item in ${items[@]}; do
echo -e ". $item"
done
echo "Quoted:"
for item in "${items[@]}"; do
echo -e ". $item"
done
set -euo pipefail
IFS=$'\n\t'
echo "Unquoted strict mode:"
for item in ${items[@]}; do
echo -e ". $item"
done
... I get this output: Unquoted:
. a
. b
. c
. d e
. f
g
Quoted:
. a
. b c
. d e
. f
g
Unquoted strict mode:
. a
. b c
. d e
. f
g
Note the output for "Quoted" and "Unquoted strict mode" are identical.(GNU bash, version 4.2.37(1)-release (x86_64-pc-linux-gnu))
My first thought: It seems like only $@, $* and variables read from the environment could be possible attack vectors. But since shell scripts can't be setuid, it's hard for me to immediately imagine how unquoting could enable a new exploit.
EDIT: the most dangerous example I can think of right now is a script like this, where a webapp invokes the script and passes a GET param as an argument:
#!/bin/bash
exec $1
But if I execute this like so: ./badscript.sh 'some-benign-command ; cat /etc/passwd'
... then passwd is not exposed, because the tokens ";", "cat" and "/etc/passwd" are passed into the argv of some-benign-command.(And if "cat /etc/password" itself can be passed as $1, then quoting won't help...)