...
- Share data between processes.
- Store auxiliary program data (for example, to save preserve memory).
- Construct and/or load classes, JAR files, and native libraries dynamically
...
- .
...
Many programs that create temporary files attempt to give them unique and unpredictable file names. This is a common attempt at mitigating the risk of creating a file in an insecure or shared directory. If the filename is not sufficiently unique or random, an attacker can guess or predict the name of the file to be created, and create a symbolic link with the same name, the final target of which is a file selected by the attacker. However, if a temporary file is created in a secure directory, an attacker cannot tamper with the file, and so the need for unpredictable names is eliminated.
Temporary files are files and consequently must conform to the requirements specified by other rules governing operations on files, including FIO00-J. Do not overwrite an existing file while attempting to create a new file, and FIO03operate on files in shared directories and FIO01-J. Create files with appropriate access permissions. Furthermore, temporary Temporary files have an the additional requirement that they must be removed before program termination.
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 daemonprocess. However, these utilities are themselves frequently vulnerable to file-based exploits and may require the use of secure directories.
We will assume that the code samples shown below obey all of the file-related rules referenced above. That is, the files are created in the current directory of the program, which is assumed to be a secure directory. Also, the files are created with appropriate access permissions, which are managed by default outside Java. The code samples below make sure that no existing file is overwritten.
Noncompliant Code Example
.
Noncompliant Code Example
This and subsequent code examples assume that files are created in a secure directory in compliance with FIO00-J. Do not operate on files in shared directories and are created with proper access permissions in compliance with FIO01-J. Create files with appropriate access permissions. Both requirements may be managed outside the Java Virtual Machine (JVM).
This noncompliant code example fails This noncompliant code example hardcodes the name of a temporary file; consequently, the file's name is predictable. However, the program makes no attempt to remove the file upon completion.:
Code Block | ||
---|---|---|
| ||
class TempFile { public static void main(String[] args) throws IOException{ File f = new File("tempnam.tmp"); if (f.exists()) { System.out.println("This file already exists"); return; } FileOutputStream fop = null; try { fop = new FileOutputStream(f); String str = "Data"; fop.write(str.getBytes()); } finally { if (f.exists()fop != null) { fop.write(str.getBytes()); try { fop.close(); } else catch (IOException x) { System.out.println("This file does not exist"); // Handle error } } } } } h2. |
Noncompliant
...
Code
...
Example
...
(
...
createTempFile()
...
,
...
deleteOnExit()
...
)
...
This
...
noncompliant
...
code
...
example
...
invokes
...
the
...
File.createTempFile()
...
method
...
, which
...
generates
...
a
...
unique
...
temporary
...
file name based
...
on
...
two
...
parameters
...
: a
...
prefix
...
and
...
an
...
extension.
...
This
...
is
...
the
...
only method from Java 6 and earlier that is designed to produce 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.
This example also uses the deleteOnExit()
method to ensure that the temporary file is deleted when the JVM terminates. However, according to the Java API [API 2014] Class File
, method deleteOnExit()
documentation,
Deletion will be attempted only for normal termination of the virtual machine, as defined by the Java Language Specification. Once deletion has been requested, it is not possible to cancel the request. This method should therefore be used with care.
Note: this method should not be used for file-locking, as the resulting protocol cannot be made to work reliably.
Consequently, the file is not deleted if the JVM terminates unexpectedly. A longstanding bug on Windows-based systems, reported as Bug ID: 4171239 [SDN 2008], causes JVMs to fail to delete a file when deleteOnExit()
is invoked before the associated stream or RandomAccessFile
is closed.
Code Block | ||
---|---|---|
| ||
method currently designed and provided for producing unique file names; although the names produced can be easily predicted. If the filename must be unpredictable, this problem can be solved by using a good random number generator to produce the prefix. This example also attempts to use the {{deleteOnExit()}} method to ensure that the temporary file is deleted when the JVM terminates. However, according to the Java API \[[API 2006|AA. Bibliography#API 06]\] Class {{File}}, method {{deleteOnExit()}} documentation: {quote} Deletion will be attempted only for normal termination of the virtual machine, as defined by the Java Language Specification. Once deletion has been requested, it is not possible to cancel the request. This method should consequently be used with care. Note: this method should not be used for file-locking, as the resulting protocol cannot be made to work reliably. {quote} Consequently, the file is not deleted if the JVM terminates unexpectedly. A longstanding bug on Windows based systems reported as [Bug ID: 4171239|http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4171239] \[[SDN 2008|AA. Bibliography#SDN 08]\] causes JVMs to fail to delete a file when {{deleteOnExit()}} is invoked before the associated stream or {{RandomAccessFile}} is closed. {code:bgColor=#FFcccc} class TempFile { public static void main(String[] args) throws IOException{ File f = File.createTempFile("tempnam",".tmp"); FileOutputStream fop = null; try { 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 if (fop != null) { try { fop.close(); } catch (IOException x) { // Handle error } } } } } |
Compliant Solution (
...
DELETE_ON_CLOSE
)
This compliant solution creates a temporary file using several methods of from Java 1.7's NIO.2 package (introduced in Java SE 7). 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 regardless of whether or not an exception occurs. Finally, the file is opened with the Java 1.7 DELETE_ON_CLOSE
option, which serves to remove removes 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)) { // writeWrite 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
When a secure directory for storing temporary files is not available, the vulnerabilities that result from using temporary files in insecure directories can be avoided by using alternative 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).
Risk Assessment
Failure to follow best practices while creating, using and deleting remove temporary files before termination can lead to result in information leakage , misinterpretations and alterations in control flowand resource exhaustion.
Rule | Severity | Likelihood | Remediation Cost | Priority | Level |
---|
FIO03-J |
high
probable
medium
P12
Medium | Probable | Medium | P8 | L2 |
Automated Detection
Tool | Version | Checker | Description | ||||||
---|---|---|---|---|---|---|---|---|---|
Parasoft Jtest |
| CERT.FIO03.ATF CERT.FIO03.REMTMP | Avoid temporary files Remove temporary files before termination |
Related Guidelines
FIO21-C. Do not create temporary files in shared directories |
VOID FIO19-CPP. Do not create temporary files in shared directories | |
, Insecure Temporary File |
, Incomplete Cleanup |
Bibliography
<ac:structured-macro ac:name="unmigrated-wiki-markup" ac:schema-version="1" ac:macro-id="b4ad4b21-657e-4521-9b5b-b23169113b1b"><ac:plain-text-body><![CDATA[
[[API 2006
[API 2014] |
createTempFile
, delete
, deleteOnExit
]]></ac:plain-text-body></ac:structured-macro>
<ac:structured-macro ac:name="unmigrated-wiki-markup" ac:schema-version="1" ac:macro-id="d1dad061-6986-4f6e-8b49-7592e47ce0fc"><ac:plain-text-body><![CDATA[
[[CVE 2008
AA. Bibliography#CVE 08]]
[CVE-2008-5354
http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2008-5354]
]]></ac:plain-text-body></ac:structured-macro>
<ac:structured-macro ac:name="unmigrated-wiki-markup" ac:schema-version="1" ac:macro-id="92981731-1ba3-45c0-a98a-656bac50510f"><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="4f8516ff-9a5a-47b9-9d94-08c19e762522"><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="f0b85ccc-401d-4970-8fd4-2ee60a27f168"><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="41c6fb1e-3ceb-4bbe-a268-02c4d8d8beec"><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>
| |
Section 11.5, "Creating a Transient File" | |
Bug JDK-4405521 | |
[SDN 2008] | Bug ID: 4171239 |
...
FIO06-J. Close resources when they are no longer needed 12. Input Output (FIO) FIO08-J. Do not log sensitive information outside a trust boundary