Assignment 4, Solutions
Part of
the homework for 22C:169, Spring 2011
|
#!/bin/tcsh # shellscript args # a shell script to echo its args # create tempfile /bin/echo > tempfile set argc = $#argv @ count = 1 while ($count <= $argc) /bin/echo argv[ ${count} ] = $argv[$count] >> tempfile @ count = $count + 1 end #output tempfile cat tempfile rm -f tempfile
Notes: The > operator creates a file and directs standard output of the command to that file. The >> operator appends the output of the command to the indicated file. The quote marks 'text' suppress all interpretation of the quoted text. The quote marks "text" permit $ substitution within the quoted text. The quote marks `text` cause the indicated text to be executed as a shell command with the output of the command replacing the indicated string. The shell variable $$ is the current process ID. Each time you launch a new shell, $$ takes on a new value local to that shell. The shell command eval evaluates its arguments as a shell command.
a) Can yhou find any vulnerabilities in this version of the script? (0.5 points)
The only potential vulnerability is on the line:
/bin/echo argv[ ${count} ] = $argv[$count] >> tempfileHere, if $argv[$count] contains characters such as ; > >> < or <<, then, depending on how the shell parses its input, there will be trouble. We can try these rather quickly:
$ ./shellscript "a;" "b>" "c<" "d>>" "e<<" argv[ 1 ] = a; argv[ 2 ] = b> argv[ 3 ] = c< argv[ 4 ] = d>> argv[ 5 ] = e<<From this, we learn that tcsh recognizes these special characters before it does dollar-sign expansion, and therefore, this shell script may be safe.
b) This script poses a possible threat to its users because of its use of a fixed file name, tempfile. How would the threat change if it used tempfile$$? (Would the threat be eliminated? If not, would the threat be reduced?) (0.5 points)
If the user happens to call a file tempfile, there will be trouble. Tempfile is a particularly likely name for a user to use. In contrast, if the script used tempfile$$, the result would be names like tempfile12698 on the first use, and possibly tempfile12713 on the next use. These are less likely to collide with fixed names chosen by the user, but collisions are still possible.
c) Suppose you changed $argv[$count] to `echo $argv[$count]`. Does this create any vulnerabilities? (Experiment!) (0.5 points)
Remarkably, no! It appears that the `echo args` construct parses its input into a sequence of arguments before it applies dollar sign substitutions, so if the argument contains a semicolon or something similar, it remains a single string, as if it is implicitly quoted with single-quotes, suppressing all further processing of the argument.
d) Suppose you changed $argv[$count] to `eval echo $argv[$count]`. Why is this different from your answer to part c? (Experiment!) (0.5 points)
Now, things begin to happen. Consider this:
$ ./shellscript '$count' '$count' '$count' argv[ 1 ] = 1 argv[ 2 ] = 2 argv[ 3 ] = 3Or, consider this:
~$ ./shellscript a '; rm tempfile;' c argv[ 3 ] = c
#!/bin/tcsh # foreachfile command # a shell script to apply command to each file in the current directory set ListOfFiles = `ls` set Count = 1 set ListLength = $#ListOfFiles while ($Count <= $ListLength) $argv $ListOfFiles[$Count] @ Count = $Count + 1 end
For example foreachfile echo will list each file name, one per line, and foreachfile ls -dl will do almost the same thing as the ls -l command, but with rather poorer formatting. Variations on this script could be useful for such things as making backups and many other things, but there are several severe problems with this script.
a) This script does not work correctly when file names contain blanks. What is the problem? (0.5 points)
Here is an example of what happened when I created a file named "for each file" with spaces in it:
$ ./foreachfile echo foreachfile for each fileWhat happened? The blanks in the file name were interpreted as delimiters between file names.
b) What is the difference between foreachfile echo and foreachfile eval echo? Does this say anything about the vulnerability of this script to shell injection attacks? (0.5 points)
Consider the following two examples:
$ ./foreachfile echo a ";" echo a ; echo foreachfile $ ./foreachfile eval echo a ";" echo a foreachfileThis makes it clear that injecting the echo command opens the door to just about everything.
c) Suppose your directory has a file names that are also Unix shell command names such as date and ls. Can you make this script execute those commands? If you can, this becomes another possible path for an injection attack. (0.5 points)
The command foreachfile with no arguments at all tries to execute all of the file names in the directory, treating each string as an indivisible lump. foreachfile eval is more dangerous because it will try to parse each file name, so if a name contains a semicolon or I/O redirection character, it will be seen.
We need to forbid blank arguments and forbid eval as an argument. Do this by adding the following before the body of the script:
if ( "$argv" == "" ) then echo argument must not be blank > /dev/stderr exit else if ( "$argv[1]" == "eval" ) then echo argument must not be eval > /dev/stderr exit endif