4

This is my first time using bash and I know that eval have some risks when using it. Can you do a code injection to this ? For example I want to run ls command and see the files.

#!/bin/bash
echo "[*] Please enter the name:"
echo -n "> "
read NAME
echo "[*] Please enter the value:"
echo -n "> "
read VALUE
declare CONFIG_$NAME=$VALUE
for VARIABLE in $(compgen -v CONFIG_)
do
   echo "- $VARIABLE: $(eval echo \$$VARIABLE)"
done
Ruslan Osmanov
  • 20,486
  • 7
  • 46
  • 60
Fish
  • 53
  • 4

3 Answers3

3

If $VARIABLE contains ; the command after it will be executed

VARIABLE=';ls'
echo "- $VARIABLE: $(eval echo \$$VARIABLE)"

The command executed by eval is

echo $;ls

Since $ isn't followed by an identifier, it's simply echoed literally. Then ls is executed.

You could also put a valid identifier at the beginning:

foo=123
VARIABLE="foo;ls"

This will execute

echo $foo;ls

so it will echo 123 then the output of ls.

Barmar
  • 741,623
  • 53
  • 500
  • 612
  • Thank you for you answer it helped a lot ! Is it possible to have VARIABLE be ;ls ? because when I try it I get 'not a valid identifier' error. – Fish Nov 05 '20 at 22:42
  • I executed the code I showed on a Mac. Maybe later versions of bash don't allow it. – Barmar Nov 05 '20 at 22:50
  • I just tried it on Linux running bash 5.0.3 and it worked as well. – Barmar Nov 05 '20 at 22:51
  • @Barmar In the script, `VARIABLE` is set from the output of `compgen -v CONFIG_` -- is there a way to get *that* to output something containing ";ls"? – Gordon Davisson Nov 05 '20 at 22:57
2

I believe this particular use of eval is safe as it only ever operates on valid identifiers, or alternatively, requires a level of control over the execution that makes the exploit itself moot.

As an attacker, I would have ignored the eval and used one of the other entry points instead, e.g.

$ ./myscript
[*] Please enter the name:
> [`date>&2`]
[*] Please enter the value:
> foo
Thu 05 Nov 2020 04:00:37 PM PST
- CONFIG_: foo
that other guy
  • 116,971
  • 11
  • 170
  • 194
1

Alternatively to using eval with Bash 3.2+, you can use indirect variable reference ${!varname}

for variable in $(compgen -v CONFIG_)
do
   echo "- $variable: ${!variable}"
done

With Bash version 4.2+ you can do the same with nameref variables declare -n var:

for variable in $(compgen -v CONFIG_)
do
  declare -n value=$variable
  echo "- $variable: $value"
done
Léa Gris
  • 17,497
  • 4
  • 32
  • 41
  • 1
    Indirect variable expansion was introduced in Bash 2.0 (1996). See [Bash-2.0 release available for FTP](https://groups.google.com/g/gnu.bash.bug/c/WE1Fa--vKw0/m/l9S7xZFP44AJ). – pjh Mar 31 '23 at 17:27