...
Code Block |
---|
|
class TempFile {
public static void main(String[] args) throws IOException{
File f = File.createTempFile("tempnam",".tmp");
FileOutputStream fop = new FileOutputStream(f);
String str = "Data";
try {
fop.write(str.getBytes());
fop.flush();
}finally {
// Stream/file still open; file will
// not be deleted on Windows systems
f.deleteOnExit(); // Delete the file when the JVM terminates
}
}
}
}
}
}
|
Noncompliant Code Example (POSIX, Java 1.7 NIO)
This noncompliant code example creates a temporary file using the newest features of Java 1.7's NIO facility. It uses the createTempFile()
method, which creates an unpredictable name. (The actual method by which the name is created is implementation-defined and undocumented.) The file is specifically created with POSIX file permissions denying access to the file to everyone except the file's creator, a similar permission set can be devised for Windows. Furthermore, the createTempFile()
will throw an exception if the file already existed. The file is opened with the Java 1.7 DELETE_ON_CLOSE
option, which serves to remove the file when it is closed. And finally, the file is opened using the try-with-resources construct, which automatically closes the file whether or not an exception occurs.
Code Block |
---|
|
class TempFile {
public static void main(String[] args) {
// POSIX file permissions for exclusive read/write
Set<PosixFilePermission> perms = PosixFilePermissions.fromString("rw-------");
FileAttribute att = PosixFilePermissions.asFileAttribute( perms);
Path tempFile = null;
try {
tempFile = Files.createTempFile( "file", ".myapp", att);
try (BufferedWriter writer = Files.newBufferedWriter(tempFile, Charset.forName("UTF8"),
StandardOpenOption.DELETE_ON_CLOSE)) {
System.out.println("Temporary file ready for writing: " + tempFile);
// write to file
}
System.out.println("Temporary file erased");
} catch (FileAlreadyExistsException x) {
System.err.println("File exists: " + tempFile);
} catch (IOException x) {
// Some other sort of failure, such as permissions.
System.err.println("Error creating temporary file: " + x);
}
}
}
|
Despite the new Java 1.7 features, this example still has several vulnerabilities. There is no mechanism to open the file with exclusive access, a feature provided by standard POSIX. Consequently the temporary file, once created, is still accessible to the user or to the system root user. Also, since the creation of the file, and the opening of the file are distinct operations, this program is still vulnerable to a time-of-check-time-of-use (TOCTOU) race condition.
Compliant Solution
Wiki Markup |
---|
To work around the file/stream termination issue, always attempt to terminate the resource normally before invoking {{deleteOnExit()}}. Using {{File.io.delete()}} to immediately delete the file is good practice, when possible; this avoids improper JVM termination related issues. Moreover, although unreliable, {{System.gc()}} may be invoked to free up related resources. Sometimes, the resources to be deleted cannot be closed first; see, for example, \[[Bug ID: 4635827|http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4635827]\]. There is no known workaround for this case. Consequently, temporary files must be created only in secure directories. |
...
Wiki Markup |
---|
\[[API 2006|AA. Bibliography#API 06]\] Class File, methods {{createTempFile}}, {{delete}}, {{deleteOnExit}}
\[[Darwin 2004|AA. Bibliography#Darwin 04]\] 11.5 Creating a Transient File
\[[J2SE 2011|AA. Bibliography#J2SE 11]\]
\[[SDN 2008|AA. Bibliography#SDN 08]\] Bug IDs: 4171239, 4405521, 4635827, 4631820
\[[Secunia 2008|AA. Bibliography#Secunia 08]\] [Secunia Advisory 20132|http://secunia.com/advisories/20132/]
\[[CVE 2008|AA. Bibliography#CVE 08]\] [CVE-2008-5354|http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2008-5354]
\[[MITRE 2009|AA. Bibliography#MITRE 09]\] [CWE ID 459 |http://cwe.mitre.org/data/definitions/459.html] "Incomplete Cleanup", [CWE ID 377|http://cwe.mitre.org/data/definitions/377.html] "Insecure Temporary File" |
...