Eval

From LQWiki
Jump to navigation Jump to search

eval is a built-in command in POSIX bourne shells (sh, bash, ksh, etc). It constructs a string from its arguments much like echo would, and the attempts to execute the result.

Since it allows one to construct a command, it should be used with great caution, or if there is input from untrusted users, not at all.

Alternatives to eval include

  • ${!VAR} in bash and some other shells for indirect variable reference.
  • using arrays instead of strings for multiparameter configuration, PARAMS=( "-s" "parameter with space" ); app "${PARAMS[@]}"; rather than PARAMS="-s \"parameter with spaces\""; eval app $PARAMS;
  • using case..esac instead of just building a command, even if it takes a few more lines of code

You can also omit eval and get the same result:

krusty:~ # export command="echo hallo"
krusty:~ # eval $command
hallo
krusty:~ # $command
hallo

Security problems

Imagine a university with a number of public access terminals for people who want to check their mail and such. It runs this program in a loop (quite compressed code, but the point is to ssh to a server, possibly substituting an abbreviation for a real host name):

#!/bin/sh
#This is an example of bad eval use
HOST_solaris=login.idi.somewhere.edu #solaris login server
HOST_bsd=bacchus.pvv.somewhere.edu   #freebsd login server

echo 'Enter your user name and server (space separated)'
read USER SERVER

host $SERVER || SERVER=`eval echo \\\$HOST_$SERVER`
[ -z $SERVER ] && echo "The server does not exist and isn't an abbreviation" \
|| ssh "$USER@$SERVER"

At first this could seem like a great idea. A student can type "rulleski login.idi.somewhere.edu" and be immediately connected and able to enter his password. Even better, he can type "rulleski solaris" and be connected to the same server, since eval echo \\\$HOST_$SERVER will run the command echo $HOST_solaris and thus find the right host.

But what happens if the user enters "rulleski ; rm -rf /"? Due to the way read works, SERVER="; rm -rf /" and eval will run

echo $HOST_; rm -rf /

Doing this would be quite benevolent however, since an alternative is making a fake password prompt and mailing people's usernames, host and passwords to yourself for further exploitation.