...
Removing temporary files when they are no longer required allows file names and other resources (such as secondary storage) to be recycled. Each program is responsible for ensuring that temporary files are removed during normal operation. There is no surefire method that can guarantee the removal of orphaned files in the case of abnormal termination, even in the presence of a finally
block, because the finally
block may fail to execute. For this reason, many systems employ temporary file cleaner utilities to sweep temporary directories and remove old files. Such utilities can be invoked manually by a system administrator or can be periodically invoked by a system process. However, these utilities are themselves vulnerable to file-based exploits and may require the use of secure directories.
Noncompliant Code Example
For this and subsequent code examples, we will assume that the files are automatically being created in a secure directory, to comply with rule FIO00-J. Do not operate on files in shared directories. We will also assume the files are created with proper access permissions, to compy with FIO01-J. Create files with appropriate access permissions. Both requirements may be managed outside the JVM.
...
Code Block | ||
---|---|---|
| ||
class TempFile { public static void main(String[] args) throws IOException{ File f = new File("tempnam.tmp"); FileOutputStream fop = new FileOutputStream(f); String str = "Data"; if (f.exists()) { fop.write(str.getBytes()); fop.close(); } else { System.out.println("This file does not exist"); } } } |
Noncompliant Code Example (createTempFile()
, deleteOnExit()
)
This noncompliant code example invokes the File.createTempFile()
method which generates a unique temporary filename based on two parameters, a prefix and an extension. This is the only method currently designed and provided for producing unique file names; although the names produced can be easily predicted. A random number generator can be used to produce the prefix if a random file name is required.
...
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 } } } |
Compliant Solution (Java 1.7), DELETE_ON_CLOSE
)
This compliant solution creates a temporary file using several methods of Java 1.7's NIO package. It uses the createTempFile()
method, which creates an unpredictable name. (The actual method by which the name is created is implementation-defined and undocumented.) Additionally, the createTempFile()
will throw an exception if the file already exists. The file is opened using the try-with-resources construct, which automatically closes the file whether or not an exception occurs. Finally, the file is opened with the Java 1.7 DELETE_ON_CLOSE
option, which serves to remove the file automatically when it is closed.
Code Block | ||
---|---|---|
| ||
class TempFile { public static void main(String[] args) { Path tempFile = null; try { tempFile = Files.createTempFile("tempnam", ".tmp"); try (BufferedWriter writer = Files.newBufferedWriter(tempFile, Charset.forName("UTF8"), StandardOpenOption.DELETE_ON_CLOSE)) { // write to file } System.out.println("Temporary file write done, 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); } } } |
Compliant Solution
If a secure directory for storing temporary files is not available, then the vulnerabilities that result from using temporary files in insecure directories can be avoided by using alternate mechanisms including:
- other IPC mechanisms such as sockets and remote procedure calls
- the low-level Java Native Interface (JNI).
- memory mapped files
- threads to share heap data within the same JVM (applies to data sharing between Java processes only)
- a secure directory that can be accessed only by application instances, provided that multiple instances of the application running on the same platform avoid competing for the same files.
Risk Assessment
Failure to follow best practices while creating, using and deleting temporary files can lead to information leakage, misinterpretations and alterations in control flow.
Rule | Severity | Likelihood | Remediation Cost | Priority | Level |
---|---|---|---|---|---|
FIO07-J | high | probable | medium | P12 | L1 |
Related Guidelines
FIO43-C. Do not create temporary files in shared directories | |
FIO43-CPP. Do not create temporary files in shared directories | |
CWE ID 377 "Insecure Temporary File" | |
| CWE ID 459 "Incomplete Cleanup" |
Bibliography
<ac:structured-macro ac:name="unmigrated-wiki-markup" ac:schema-version="1" ac:macro-id="2e7fa4aebbfca380-03aa8d9c-4e934777-95b4b6ff-0cd70edbe052f8675abeac8a"><ac:plain-text-body><![CDATA[ | [[API 2006 | AA. Bibliography#API 06]] | Class File, methods | ]]></ac:plain-text-body></ac:structured-macro> | |
<ac:structured-macro ac:name="unmigrated-wiki-markup" ac:schema-version="1" ac:macro-id="4c97308e0c1d0f00-fbf863bd-4f064a62-83a4bb26-fdb8f44b912be74f4f64a648"><ac:plain-text-body><![CDATA[ | [[Darwin 2004 | AA. Bibliography#Darwin 04]] | 11.5 Creating a Transient File | ]]></ac:plain-text-body></ac:structured-macro> | |
<ac:structured-macro ac:name="unmigrated-wiki-markup" ac:schema-version="1" ac:macro-id="757c6cc3438994a9-d4bea934-4ea748b1-9b919733-2e13a5244073c9d86415d070"><ac:plain-text-body><![CDATA[ | [[J2SE 2011 | AA. Bibliography#J2SE 11]] |
| ]]></ac:plain-text-body></ac:structured-macro> | |
<ac:structured-macro ac:name="unmigrated-wiki-markup" ac:schema-version="1" ac:macro-id="e7e8d23256768dc0-e6e07706-47df45c0-b410a69c-0e4af6af4b2a25d0f85b91cc"><ac:plain-text-body><![CDATA[ | [[SDN 2008 | AA. Bibliography#SDN 08]] | Bug IDs: 4171239, 4405521, 4635827, 4631820 | ]]></ac:plain-text-body></ac:structured-macro> | |
<ac:structured-macro ac:name="unmigrated-wiki-markup" ac:schema-version="1" ac:macro-id="9f027de395e921a6-ab7bef62-41f74d4e-bd42a49a-c2b737d2118665aa89c98522"><ac:plain-text-body><![CDATA[ | [[Secunia 2008 | AA. Bibliography#Secunia 08]] | [Secunia Advisory 20132 | http://secunia.com/advisories/20132/] | ]]></ac:plain-text-body></ac:structured-macro> |
...