Next: Race Conditions with -print and -print0, Previous: Changing the Current Working Directory, Up: Security Considerations for find
The -exec action causes another program to be run. It is passed the name of the file which is being considered at the time. The invoked program will then - normally - perform some action on that file. Once again, there is a race condition which can be exploited here. We shall take as a specific example the command
find /tmp -path /tmp/umsp/passwd -exec /bin/rm
In this simple example, we are identifying just one file to be deleted
and invoking /bin/rm
to delete it. A problem exists because
there is a time gap between the point where find
decides that
it needs to process the -exec action and the point where the
/bin/rm
command actually issues the unlink()
system
call. Within this time period, an attacker can rename the
/tmp/umsp directory, replacing it with a symbolic link to
/etc. There is no way for /bin/rm
to determine that it
is working on the same file that find
had in mind. Once the
symbolic link is in place, the attacker has persuaded find
to
cause the deletion of the /etc/passwd file, which is not the
effect intended by the command which was actually invoked.
One possible defence against this type of attack is to modify the
behaviour of -exec so that the /bin/rm
command is run
with the argument ./passwd and a suitable choice of working
directory. This would allow the normal sanity check that find
performs to protect against this form of attack too. Unfortunately,
this strategy cannot be used as the POSIX standard specifies that the
current working directory for commands invoked via -exec must
be the same as the current working directory from which find
was invoked. This means that the -exec action is inherently
insecure and can't be fixed.
GNU find
implements a more secure variant of the -exec
action, -execdir. The -execdir action
ensures that it is not necessary to dereference subdirectories to
process target files. The current directory used to invoke programs
is the same as the directory in which the file to be processed exists
(/tmp/umsp in our example, and only the basename of the file to
be processed is passed to the invoked command, with a ./
prepended (giving ./passwd in our example).
The -execdir action refuses to do anything if the current directory is included in the $PATH environment variable. This is necessary because -execdir runs programs in the same directory in which it finds files – in general, such a directory might be writable by untrusted users. For similar reasons, -execdir does not allow {} to appear in the name of the command to be run.