11 Security Considerations

Security considerations are important if you are using ‘find’ or ‘xargs’ to search for or process files that don’t belong to you or which other people have control.

Security considerations relating to ‘locate’ may also apply if you have files which you do not want others to see.

The most severe forms of security problems affecting ‘find’ and related programs are when third parties bring about a situation allowing them to do something they would normally not be able to accomplish.

This is called privilege elevation.

This might include deleting files they would not normally be able to delete.

It is common for the operating system to periodically invoke ‘find’ for self-maintenance purposes.

These invocations of ‘find’ are particularly problematic from a security point of view as these are often invoked by the superuser and search the entire filesystem hierarchy.

Generally, the severity of any associated problem depends on what the system is going to do with the files found by ‘find’.

11.1 Levels of Risk

There are some security risks inherent in the use of ‘find’, ‘xargs’ and (to a lesser extent) ‘locate’.

The severity of these risks depends on what sort of system you are using:

High risk

Multi-user systems where you do not control (or trust) the other users, and on which you execute ‘find’, including areas where those other users can manipulate the filesystem (for example beneath ‘/home’ or ‘/tmp’).

Medium Risk

Systems where the actions of other users can create file names chosen by them, but to which they don’t have access while ‘find’ is being run. This access might include leaving programs running (shell background jobs, ‘at’ or ‘cron’ tasks, for example). On these sorts of systems, carefully written commands (avoiding use of ‘-print’ for example) should not expose you to a high degree of risk. Most systems fall into this category.

Low Risk

Systems to which untrusted parties do not have access, cannot create file names of their own choice (even remotely) and which contain no security flaws which might enable an untrusted third party to gain access. Most systems do not fall into this category because there are many ways in which external parties can affect the names of files that are created on your system. The system on which I am writing this for example automatically downloads software updates from the Internet; the names of the files in which these updates exist are chosen by third parties(1).

In the discussion above, risk denotes the likelihood that someone can cause ‘find’, ‘xargs’, ‘locate’ or some other program which is controlled by them to do something you did not intend. The levels of risk suggested do not take any account of the consequences of this sort of event.

That is, if you operate a low risk type system, but the consequences of a security problem are disastrous, then you should still give serious thought to all the possible security problems, many of which of course will not be discussed here - this section of the manual is intended to be informative but not comprehensive or exhaustive.

If you are responsible for the operation of a system where the consequences of a security problem could be very important, you should do two things:

  1. Define a security policy which defines who is allowed to do what on your system.
  2. Seek competent advice on how to enforce your policy, detect breaches of that policy, and take account of any potential problems that might fall outside the scope of your policy.

Footnotes (1) Of course, I trust these parties to a large extent anyway, because I install software provided by them; I choose to trust them in this way, and that’s a deliberate choice

11.2 Security Considerations for ‘find’

Some of the actions ‘find’ might take have a direct effect; these include ‘-exec’ and ‘-delete’. However, it is also common to use ‘-print’ explicitly or implicitly, and so if ‘find’ produces the wrong list of file names, that can also be a security problem; consider the case for example where ‘find’ is producing a list of files to be deleted. We normally assume that the ‘find’ command line expresses the file selection criteria and actions that the user had in mind - that is, the command line is “trusted” data. From a security analysis point of view, the output of ‘find’ should be correct; that is, the output should contain only the names of those files which meet the user’s criteria specified on the command line. This applies for the ‘-exec’ and ‘-delete’ actions; one can consider these to be part of the output. On the other hand, the contents of the filesystem can be manipulated by other people, and hence we regard this as “untrusted” data. This implies that the ‘find’ command line is a filter which converts the untrusted contents of the filesystem into a correct list of output files. The filesystem will in general change while ‘find’ is searching it; in fact, most of the potential security problems with ‘find’ relate to this issue in some way. “Race conditions” are a general class of security problem where the relative ordering of actions taken by ‘find’ (for example) and something else are critically important in getting the correct and expected result(1) . For ‘find’, an attacker might move or rename files or directories in the hope that an action might be taken against a file which was not normally intended to be affected. Alternatively, this sort of attack might be intended to persuade ‘find’ to search part of the filesystem which would not normally be included in the search (defeating the ‘-prune’ action for example).

Footnotes (1) This is more or less the definition of the term “race condition”

11.2.1 Problems with ‘-exec’ and filenames

It is safe in many cases to use the ‘-execdir’ action with any file name.

Because ‘-execdir’ prefixes the arguments it passes to programs with ‘./’, you will not accidentally pass an argument which is interpreted as an option.

For example the file ‘-f’ would be passed to ‘rm’ as ‘./-f’, which is harmless.

However, your degree of safety does depend on the nature of the program you are running.

risky!

Constructs such as these two commands

find -exec sh -c "something {}" \;
find -execdir sh -c "something {}" \;

are very dangerous.

The reason for this is that the ’{}’ is expanded to a filename which might contain a semicolon or other characters special to the shell. If for example someone creates the file ‘/tmp/foo; rm -rf $HOME’ then the two commands above could delete someone’s home directory.

So for this reason do not run any command which will pass untrusted data (such as the names of files) to commands which interpret arguments as commands to be further interpreted (for example ‘sh’). In the case of the shell, there is a clever workaround for this problem:

safer

  find -exec sh -c 'something "$@"' sh {} \;
  find -execdir sh -c 'something "$@"' sh {} \;

This approach is not guaranteed to avoid every problem, but it is much safer than substituting data of an attacker’s choice into the text of a shell command.

11.2.2 Changing the Current Working Directory

As ‘find’ searches the filesystem, it finds subdirectories and then searches within them by changing its working directory. First, ‘find’ reaches and recognises a subdirectory. It then decides if that subdirectory meets the criteria for being searched; that is, any ‘-xdev’ or ‘-prune’ expressions are taken into account. The ‘find’ program will then change working directory and proceed to search the directory. A race condition attack might take the form that once the checks relevant to ‘-xdev’ and ‘-prune’ have been done, an attacker might rename the directory that was being considered, and put in its place a symbolic link that actually points somewhere else. The idea behind this attack is to fool ‘find’ into going into the wrong directory. This would leave ‘find’ with a working directory chosen by an attacker, bypassing any protection apparently provided by ‘-xdev’ and ‘-prune’, and any protection provided by being able to not list particular directories on the ‘find’ command line. This form of attack is particularly problematic if the attacker can predict when the ‘find’ command will be run, as is the case with ‘cron’ tasks for example. GNU ‘find’ has specific safeguards to prevent this general class of problem. The exact form of these safeguards depends on the properties of your system.

11.2.2.1 ‘O_NOFOLLOW’

If your system supports the ‘O_NOFOLLOW’ flag (1) to the ‘open(2)’ system call, ‘find’ uses it to safely change directories. The target directory is first opened and then ‘find’ changes working directory with the ‘fchdir()’ system call. This ensures that symbolic links are not followed, preventing the sort of race condition attack in which use is made of symbolic links. If for any reason this approach does not work, ‘find’ will fall back on the method which is normally used if ‘O_NOFOLLOW’ is not supported. You can tell if your system supports ‘O_NOFOLLOW’ by running find —version This will tell you the version number and which features are enabled. For example, if I run this on my system now, this gives: find (GNU findutils) 4.8.0 Copyright (C) 2021 Free Software Foundation, Inc. License GPLv3+: GNU GPL version 3 or later
https://gnu.org/licenses/gpl.html. This is free software: you are free to change and redistribute it. There is NO WARRANTY, to the extent permitted by law. Written by Eric B. Decker, James Youngman, and Kevin Dalley. Features enabled: D_TYPE O_NOFOLLOW(enabled) LEAF_OPTIMISATION
FTS(FTS_CWDFD) CBO(level=2) Here, you can see that I am running a version of ‘find’ which was built from the development (git) code prior to the release of findutils-4.5.12, and that several features including ‘O_NOFOLLOW’ are present. ‘O_NOFOLLOW’ is qualified with “enabled”. This simply means that the current system seems to support ‘O_NOFOLLOW’. This check is needed because it is possible to build ‘find’ on a system that defines ‘O_NOFOLLOW’ and then run it on a system that ignores the ‘O_NOFOLLOW’ flag. We try to detect such cases at startup by checking the operating system and version number; when this happens you will see ‘O_NOFOLLOW(disabled)’ instead.

Footnotes (1) GNU/Linux (kernel version 2.1.126 and later) and FreeBSD (3.0-CURRENT and later) support this

11.2.2.2 Systems without ‘O_NOFOLLOW’

The strategy for preventing this type of problem on systems that lack support for the ‘O_NOFOLLOW’ flag is more complex. Each time ‘find’ changes directory, it examines the directory it is about to move to, issues the ‘chdir()’ system call, and then checks that it has ended up in the subdirectory it expected. If all is as expected, processing continues as normal. However, there are two main reasons why the directory might change: the use of an automounter and someone removing the old directory and replacing it with something else while ‘find’ is trying to descend into it. Where a filesystem “automounter” is in use it can be the case that the use of the ‘chdir()’ system call can itself cause a new filesystem to be mounted at that point. On systems that do not support ‘O_NOFOLLOW’, this will cause ‘find”s security check to fail. However, this does not normally represent a security problem, since the automounter configuration is normally set up by the system administrator. Therefore, if the ‘chdir()’ sanity check fails, ‘find’ will make one more attempt(1). If that succeeds, execution carries on as normal. This is the usual case for automounters. Where an attacker is trying to exploit a race condition, the problem may not have gone away on the second attempt. If this is the case, ‘find’ will issue a warning message and then ignore that subdirectory. When this happens, actions such as ‘-exec’ or ‘-print’ may already have taken place for the problematic subdirectory. This is because ‘find’ applies tests and actions to directories before searching within them (unless ‘-depth’ was specified). Because of the nature of the directory-change operation and security check, in the worst case the only things that ‘find’ would have done with the directory are to move into it and back out to the original parent. No operations would have been performed within that directory.

Footnotes (1) This may not be the case for the fts-based executable

11.2.3 Race Conditions with ‘-exec’

The ‘-exec’ action causes another program to be run. It passes to the program the name of the file which is being considered at the time. The invoked program will typically then 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 to delete the file from the filesystem. 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 with ‘-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.

11.2.4 Race Conditions with ‘-print’ and ‘-print0’

The ‘-print’ and ‘-print0’ actions can be used to produce a list of files matching some criteria, which can then be used with some other command, perhaps with ‘xargs’. Unfortunately, this means that there is an unavoidable time gap between ‘find’ deciding that one or more files meet its criteria and the relevant command being executed. For this reason, the ‘-print’ and ‘-print0’ actions are just as insecure as ‘-exec’. In fact, since the construction find … -print | xargs … does not cope correctly with newlines or other “white space” in file names, and copes poorly with file names containing quotes, the ‘-print’ action is less secure even than ‘-print0’.

11.3 Security Considerations for ‘xargs’

The description of the race conditions affecting the ‘-print’ action of ‘find’ shows that ‘xargs’ cannot be secure if it is possible for an attacker to modify a filesystem after ‘find’ has started but before ‘xargs’ has completed all its actions. However, there are other security issues that exist even if it is not possible for an attacker to have access to the filesystem in real time. Firstly, if it is possible for an attacker to create files with names of their choice on the filesystem, then ‘xargs’ is insecure unless the ‘-0’ option is used. If a file with the name ‘/home/someuser/foo/bar\n/etc/passwd’ exists (assume that ‘\n’ stands for a newline character), then ‘find … -print’ can be persuaded to print three separate lines: /home/someuser/foo/bar /etc/passwd If it finds a blank line in the input, ‘xargs’ will ignore it. Therefore, if some action is to be taken on the basis of this list of files, the ‘/etc/passwd’ file would be included even if this was not the intent of the person running find. There are circumstances in which an attacker can use this to their advantage. The same consideration applies to file names containing ordinary spaces rather than newlines, except that of course the list of file names will no longer contain an “extra” newline. This problem is an unavoidable consequence of the default behaviour of the ‘xargs’ command, which is specified by the POSIX standard. The only ways to avoid this problem are either to avoid all use of ‘xargs’ in favour for example of ‘find -exec’ or (where available) ‘find -execdir’, or to use the ‘-0’ option, which ensures that ‘xargs’ considers file names to be separated by ASCII NUL characters rather than whitespace. However, useful as this option is, the POSIX standard does not make it mandatory. POSIX also specifies that ‘xargs’ interprets quoting and trailing whitespace specially in filenames, too. This means that using ‘find … -print | xargs …’ can cause the commands run by ‘xargs’ to receive a list of file names which is not the same as the list printed by ‘find’. The interpretation of quotes and trailing whitespace is turned off by the ‘-0’ argument to ‘xargs’, which is another reason to use that option.

11.4 Security Considerations for ‘locate’

11.4.1 Race Conditions

It is fairly unusual for the output of ‘locate’ to be fed into another command. However, if this were to be done, this would raise the same set of security issues as the use of ‘find … -print’. Although the problems relating to whitespace in file names can be resolved by using ‘locate”s ‘-0’ option, this still leaves the race condition problems associated with ‘find … -print0’. There is no way to avoid these problems in the case of ‘locate’.

11.5 Summary

Where untrusted parties can create files on the system, or affect the names of files that are created, all uses for ‘find’, ‘locate’ and ‘xargs’ have known security problems except the following:

Informational use only Uses where the programs are used to prepare lists of file names upon which no further action will ever be taken.

‘-delete’ Use of the ‘-delete’ action with ‘find’ to delete files which meet specified criteria

‘-execdir’ Use of the ‘-execdir’ action with ‘find’ where the ‘PATH’ environment variable contains directories which contain only trusted programs.

11.6 Further Reading on Security

While there are a number of books on computer security, there are also useful articles on the web that touch on the issues described above: