Anything that modifies the operation of some utility can be used to attack. The next section is about environment variables, here we look at option flags.
A typical program invocation looks like
foo -l -s file1 file2 ...
. Interesting things
happen when files have names starting with a dash.
Some totally misguided people like to have all files
in their home directory, and add a file -i
as a protection against rm *
. Yecch.
Some Unix-type systems supported setuid shell scripts.
If the script starts with #! /bin/sh
and is called
foo
, the result of the invocation foo args
was equivalent to that of /bin/sh foo args
, so that
the shell would execute the commands in the script foo
with parameters args
. But now, what if you call the script
-c
(maybe by making a link or a symlink)? The command
/bin/sh -c args
is executed. The shell will do
the commands given in args
and does not look at the
script at all. This was the end of the suid shell scripts.
In 1994 it was discovered that on all AIX and all Linux systems
login -froot
would give an immediate root shell
(and rlogin host -l -froot
a remote root).
Indeed, on a trusted network, the rlogind
server would do login -p -h -f user
in case user
had already been authenticated by the client, and
login -p -h user
otherwise. Thus, the -f
flag
means: no further authentication required. But, the option parser
of login
was willing to parse -fuser
as -f user
...
(And old bugs never die: in 2007 Solaris was found to have precisely
the same vulnerability when login was invoked via telnet.)
In 2004 it was noticed that opening a telnet://
URL
where the hostname starts with a dash causes the hostname
to be interpreted as telnet
option. Several browsers
have such flaws. For example, Opera on Windows when given
telnet://-ffilename
will overwrite the file filename
(in the Opera directory) with the connection log, and Opera on Linux
when given telnet://-nfilename
will overwrite filename
in the user's home directory.
On a GNU system one can prevent most of such misinterpretations
by using a --
separator between options and filenames.
Unix scripts are very bad at handling filenames with embedded spaces. This is just laziness of the authors - it has always been true that a filename could contain arbitrary bytes except for NUL and slash.
Many cron
scripts contain stuff like
find / -type f -name core +mtime 7 -print | xargs rm
to remove old core files, or old temporary files in /tmp
or so. Let us try.
% cd /tmp % mkdir -p " /etc/passwd " % touch " /etc/passwd "/core % find . -type f -name core -print | xargs rm rm: cannot remove `./': Is a directory rm: cannot remove `/etc/passwd': Permission denied rm: cannot remove `/core': No such file or directoryOK, so if this command is run by root we can delete arbitrary files by using filenames that end in a space (or are just a single space).
A more careful script would have
find . -type f -name core -print0 | xargs -0 rm
.