8

Is there any way in Java to write out to a temporary file securely?

As far as I can tell, the only way to create a temporary file (createTempFile) does't actually open it at the same time, so there's a race condition between file open & file write. Am I missing something? I couldn't find the C source code behind createFileExclusively(String) in UnixFileSystem.java, but I doubt it can really do anything since the file open occurs in the Java code after the temp file is created (unless it tries to do something with file locks?).

The problem

Between when the temporary file is created & you open it, a malicious attacker could unlink that temporary file & put malicious stuff there. For example, an attacker could create a named pipe to read sensitive data. Or similarly if you eventually copy the file by reading it, then the named pipe could just ignore everything written & supply malicious content to be read.

I remember reading of numerous examples of temporary file attacks in the past 10+ years that exploit the race condition between when the name appears in the namespace and when the file is actually opened.

Hopefully a mitigating factor is that Java set's the umask correctly so a less-privileged user can't read/write to the file and typically the /tmp directory restricts permissions properly so that you can't perform an unlink attack.

Of course if you pass a custom directory for the temporary file that's owned by a less-privileged user who's compromised, the user could do an unlink attack against you. Hell, with inotify, it's probably even easier to exploit the race condition than just a brute force loop that does a directory listing.

Vitali
  • 3,411
  • 2
  • 24
  • 25

4 Answers4

2

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

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 How to create a temporary directory/folder 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

Community
  • 1
  • 1
  • read the other comments I posted about why createTempFile isn't good enough as compared to the "gold" standard of mkstemp (the race condition mkstemp avoids is present in createTempFile). But yes, I don't think there's a better way built-in into Java to create a file in the namespace & open it in 1 command. – Vitali Oct 25 '12 at 05:44
  • 1
    @Vitali - I believe using the java.nio.file.Files (note that it's not the same class path as mentioned above) methods createTempFile and createTempDirectory do what you want, because you can specify a File Attribute parameter which includes specific atomic options, including permissions to be set when creating the directory/file (which should be similar to how mkstemp handles things). References: https://docs.oracle.com/javase/7/docs/api/java/nio/file/Files.html#createTempFile | https://docs.oracle.com/javase/7/docs/api/java/nio/file/attribute/FileAttribute.html – Ian Gallagher Dec 03 '15 at 00:11
  • 1
    The key thing that mkstemp does it open the file (so you know you opened the newly created file, and not a replacement). None of these Java solutions do that. – OrangeDog Aug 02 '16 at 11:01
1

Since Java 7 we have OpenOption.

An object that configures how to open or create a file.

Objects of this type are used by methods such as newOutputStream, newByteChannel, FileChannel.open, and AsynchronousFileChannel.open when opening or creating a file.

Of particular interest is StandardOpenOptions.CREATE_NEW.

Create a new file, failing if the file already exists. The check for the existence of the file and the creation of the file if it does not exist is atomic with respect to other file system operations.

So, you can do something like this:

FileChannel mkstemp() {
    Path path = Files.createTempFile(null, null);
    Files.delete(path);
    return FileChannel.open(path, WRITE, CREATE_NEW);
}

Implementing the same template behaviour is left as exercise to the reader.

OrangeDog
  • 36,653
  • 12
  • 122
  • 207
0

Keep in mind that on many systems, just because a file doesn't have a name doesn't at all mean it's inaccessible. For example, on Linux open file descriptors are available in /proc/<pid>/fd/<fdno>. So you should make sure that your use of temporary files is secure even if someone knows / has a reference to the open file.

You might get a more useful answer if you specify exactly what classes of attacks you are trying to prevent.

Steven Schlansker
  • 37,580
  • 14
  • 81
  • 100
  • But that typically requires elevated privileges, so you don't care; if the attacker has permissions to look into your memory space (which is essentially what being able to access your fds is), then there's nothing you can do. They can access /proc//maps & they can even read/write your memory raw via /proc//mem. – Vitali May 05 '12 at 02:33
0

Secure against other ordinary userid's? Yes, on any properly functioning multi-user system.

Secure against the your own userid or the superuser? No.

Chris Stratton
  • 39,853
  • 6
  • 84
  • 117