Creating temporary files securely

Creating temporary files  is a common use case in virtually every program. Virtually every programming language has a simple and secure way to create temporary files. Sadly many programmers fail to use them, creating security vulnerabilities in their applications. So in alphabetical order here is a list of programming languages and how to create a temporary file securely. If I’m wrong, please let me know. Note: when searching for a secure temporary file creation function/method/etc. looking for “mkstemp” is a quick way to find most of them. Please note a lot of sites (e.g. http://rosettacode.org/wiki/Secure_temporary_file) contain old/wrong information.

O_CREAT and O_EXCL (and similar)

When opening a temporary file in C you MUST use O_CREAT and O_EXCL together to ensure that the file is only created if the file does not exist. Otherwise between the time you check for the existence of a file and the time you create the file an attacker may be able to create a file with the same name. The good news here is that virtually every secure temporary file creation function/library does this or an equivalent option. To quote mkstemp():

The mkstemp() function shall replace the contents of the string pointed to by template by a unique filename, and return a file descriptor for the file open for reading and writing. The function thus prevents any possible race condition between testing whether the file exists and opening it for use.

Why “unique” names are not enough, but are generally not a huge problem

People often think that creating a file with a “unique” name in /tmp (e.g. “/tmp/myprogram-output.log”) is sufficient to safely create a temporary file. However if you create the file with a known or easily guessed name (e.g. a static name set in the source code or a config file) an attacker can create the file first and then your application will be unable to, creating a denial of service condition potentially.

However the names don’t have to be terribly unique. For example if you use mkstemp() with 10 random characters (the default) gives on the order of 839,299,365,868,340,224 possible file names. Any attacker able to create enough files to force a collision of the name would be able to fill up the /tmp directory in any event (unless you have an absurdly large /tmp directory that is several exabytes in size, which won’t be a problem for some time).

Unexpected temporary files

It should also be noted that many programs create temporary files. Text editors and other file editors may create temporary file saves in /tmp or /var/tmp and so on.

The problem with $TMP, $TEMP, $TMPDIR, $TEMPDIR and so on

One note: if you’re going to use environmental variables you’d better make sure you sanitize them and ensure they aren’t overly long. User controlled environmental variables are just that, user controlled. I can’t find a good set of libraries or code to sanitize these variables before use, if anyone knows of such a thing please contact me ([email protected]).

Bash

Simply use “mktemp” (“man mktemp” for details). Use “-d” or “–directory” for creating directories.

C

use mkstemp() (“man mkstemp” for details) for files

use mkdtemp() (“man mkdtemp” for details) for directories

tmpfile() is another option - Creates a temporary binary file, open for update (wb+ mode — see fopen for details). The filename is guaranteed to be different from any other existing file.

C++

use mkstemp() (“man mkstemp” for details)

use mkdtemp() (“man mkdtemp” for details) for directories

tmpfile() is another option - Creates a temporary binary file, open for update (wb+ mode — see fopen for details). The filename is guaranteed to be different from any other existing file.

On Windows use GetTempPath() and GetTempFileName () (same names in C#)

C#

Path.GetTempFileName() http://msdn.microsoft.com/en-us/library/system.io.path.gettempfilename(v=vs.80).aspx

Cocoa

http://stackoverflow.com/questions/215820/how-do-i-create-a-temporary-file-with-cocoa

Google Go (golang)

So ioutil.TempDir and ioutil.TempFile automatically appends a uint32 and has default permissions of 0600. Well done.

http://golang.org/pkg/io/ioutil/#TempDir

Use this and you’re safe. Just a note: io.TempDir returns the value of the temporary directly (e.g. /tmp).

Java

use java.io.File.createTempFile() – some interesting info at http://www.veracode.com/blog/2009/01/how-boring-flaws-become-interesting/

for directories there is a helpful posting at http://stackoverflow.com/questions/617414/create-a-temporary-directory-in-java

Java 7

for files use java.io.File.createTempFile()

for directories use createTempDirectory()

http://docs.oracle.com/javase/7/docs/api/java/nio/file/Files.html

Lisp

http://stackoverflow.com/questions/1384972/common-lisp-function-or-idiom-for-creating-a-temporary-file-name

nodejs

http://stackoverflow.com/questions/7055061/nodejs-temporary-file-name

Perl

use mkstemp()

http://perldoc.perl.org/File/Temp.html#MKTEMP-FUNCTIONS

Python

Simply use “mkstemp” for files and “mkdtemp” for directories from the “tempfile” module:

http://docs.python.org/library/tempfile.html#tempfile.mkstemp

QT

use QTemporaryFile for files:

http://qt-project.org/doc/qt-4.8/qtemporaryfile.html

use  for QTemporaryDir directories:

http://qt-project.org/doc/qt-5.0/qtemporarydir.html

Ruby

use Tempfile for files:

http://www.ruby-doc.org/stdlib-1.9.3/libdoc/tempfile/rdoc/Tempfile.html#method-c-new

use tmpdir for directories (require ‘tmpdir’ and then you can “Dir.mktmpdir”):

http://www.ruby-doc.org/stdlib-1.9.3/libdoc/tmpdir/rdoc/index.html

Making per user /tmp directories

Using PAM you can also make per user /tmp directories using polyinstantiation http://www.ibm.com/developerworks/linux/library/l-polyinstantiation/

If you have a system with many users (e.g. a shell server or web host) this is a great way to avoid the whole /tmp mess at the system level rather than trying to ensure your applications are properly written.

Monitoring /tmp for activity

So how can we be sure our changes work and temporary directories and files are being created safely? Conversely how can we monitor /tmp to watch for programs that use /tmp improperly or in unsafe ways? Linux has an inotify subsystem that allows you to monitor a file(s) or directory(s) (including recursively) for file and directory related activity (creation, deletion, modification, etc.). The downside of inotify is that, as far as I can tell, there is no way to list which process was responsible (so if you have a large application and multiple applications running it may be difficult to track down which one specifically created the file/etc.

To use inotify use either the “inotify-tools” or “pyinotify” programs, I prefer pynitofy, the output is really easy to read:

# /usr/bin/pyinotify /tmp/
<Event dir=True mask=0x40000100 maskname=IN_CREATE|IN_ISDIR \
name=foo.ooCHP2tb1adt path=/tmp pathname=/tmp/foo.ooCHP2tb1adt wd=1 >

You can also use SELinux, running permissive mode simply disable all access to /tmp and then run your application(s). The log files will show any accesses of /tmp including the process information.

Auditing for /tmp file vulnerabilities

It’s not hard, mostly I just do:

find ./ -type f -exec grep /tmp {} +

and if they wrote the code using the above techniques it is probably safe, if it is written any other way it’s probably wrong.

Which directory should you use?

You should be using /var/run/something/ or /run/something/ that is setup in advance and secured for the users/groups that require it.

Tags: , , ,

2 Responses to “Creating temporary files securely”

  1. Rubygem Ruby Parser Multiple Vulnerabilities | Web Security Watch Says:

    [...] http://kurt.seifried.org/2012/03/14/creating-temporary-files-securely/ [...]

  2. Eric Christensen Says:

    Reblogged this on Sparks' Linux Journal and commented:
    Secure coding advice for dealing with temporary files.

Leave a Reply

Please log in using one of these methods to post your comment:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s


Follow

Get every new post delivered to your Inbox.

%d bloggers like this: