Tuesday, December 7, 2010

Tips for Securely Using Temporary Files in Linux Scripts

SkyHi @ Tuesday, December 07, 2010
Over the years, I've written hundreds, if not thousands, of shell scripts. With the ease at which you can redirect input and output within a shell script, many sysadmins store data in temporary files for processing purposes. In some situations scripts become essential to the day-to-day operations of a system and as such, may end up running on a regular basis via crontab – never to be looked at again.
Unfortunately, some sysadmins who write scripts might store sensitive data in temporary files, don't restrict access to temporary files, and might forget to remove them from the system when they are no longer needed. In many cases, they use them when it isn't even necessary. The beauty of Linux and UNIX is that there are hundreds of ways to accomplish the same task. I will keep my Bash examples simple so you can focus on grasping the general concepts.

Restrict access to temporary files

This is the most commonly forgotten step. If you are like most sysadmins who write temporary files to /tmp or /var/tmp, set your umask before file creation.
# cut -f1 -d: /etc/passwd > /tmp/test
# ls -l /tmp/test
-rw-r--r-- 1 root root 207 Dec  6 11:56 /tmp/test

# rm -f /tmp/test
Now, let's set the umask, create the file again, and check its access controls:
# umask 077
# cut -f1 -d: /etc/passwd > /tmp/test
# ls -l /tmp/test
-rw------- 1 root root 207 Dec  6 11:58 /tmp/test

# rm -f /tmp/test
As you can see, the more restrictive umask only grants the file owner read and write permission. Additionally, instead of writing temporary files to /tmp or /var/tmp, write the files to a dedicated, private area such as one under the user account's home directory. Limit access to this directory with permissions such as 0700.

Use a random string as the filename

To reduce the likelihood that someone knows the exact name of the temporary file your script creates, avoid using file name prefixes and use random characters as the filename. For example:
# umask 077
# tempfile=$(head -c 12 /dev/urandom |mimencode  |tr -d "/")
# echo $tempfile

# cut -f1 -d: /etc/passwd > /tmp/$tempfile
# ls -l /tmp/$tempfile
-rw------- 1 root root 207 Dec  6 12:10 /tmp/wwiboOPRHbozVuce

# rm -f /tmp/$tempfile

Don't use temporary files at all

Of course, the safest method is to do in-line processing using pipes, a subshell environment, or a variable. For example, if you wanted an alphabetical listing of user accounts simply use a pipe:
# cut -f1 -d: /etc/passwd | sort -u
or even:
# sort -u -t: -k1 /etc/passwd |cut -f1 -d:
If you wanted to perform an action on each account on the system, invoke a subshell on a for...loop such as:
for user in $(cut -f1 -d: /etc/passwd)
    printf "some action on %s\n" $user


In summary, take a look at your /var/tmp and /tmp directories. Do they have a bunch of strange files which are open to the world? Take inventory of all of the scripts running on your system especially those which are executed regularly via crontab. Make sure you clearly understand what they are doing and if they are creating any temporary files. If they do, try some of the aforementioned tips to help secure them.