...
* If the program terminates abnormally, this behavior is implementation-defined.
Securely creating temporary files is error prone and dependent on the version of the C runtime library used, the operating system, and the file system. Code that works for a locally mounted file system, for example, may be vulnerable when used with a remotely mounted file system. Moreover, none of these functions are without problems. The only secure solution is not to create temporary files in shared directories.
...
Privileged programs that create temporary files in world-writable directories can be exploited to overwrite protected system files. An attacker who can predict the name of a file created by a privileged program can create a symbolic link (with the same name as the file used by the program) to point to a protected system file. Unless the privileged program is coded securely, the program will follow the symbolic link instead of opening or creating the file that it is supposed to be using. As a result, a protected system file to which the symbolic link points can be overwritten when the program is executed [HP 2003]. Unprivileged programs can be similarly exploited to overwrite protected user files.
...
Exclusive access grants unrestricted file access to the locking process while denying access to all other processes and eliminates the potential for a race condition on the locked region. (See Secure Coding in C and C++, Chapter 7 [Seacord 2005a].)
Files, or regions of files, can be locked to prevent two processes from concurrent access. Windows supports two types of file locks:
...
Removing temporary files when they are no longer required allows file names and other resources (such as secondary storage) to be recycled. In the case of abnormal termination, there is no sure method that can guarantee the removal of orphaned files. For this reason, temporary file cleaner utilities, which are invoked manually by a system administrator or periodically run by a daemon to sweep temporary directories and remove old files, are widely used. However, these utilities are themselves vulnerable to file-based exploits and often require the use of shared directories. During normal operation, it is the responsibility of the program to ensure that temporary files are removed either explicitly or through the use of library routines, such as tmpfile_s
, which guarantee temporary file deletion upon program termination.
...
The following noncompliant code example attempts to remedy the problem by generating the file name at runtime using tmpnam()
. The C tmpnam()
function generates a string that is a valid file name and that is not the same as the name of an existing file [ISO/IEC 9899:2011]. Files created using strings generated by the tmpnam()
function are temporary in that their names should not collide with those generated by conventional naming rules for the implementation. The function is potentially capable of generating TMP_MAX
different strings, but any or all of them may already be in use by existing files.
...
The next noncompliant code example attempts to remedy the problem by using the POSIX open()
function and providing a mechanism to indicate whether an existing file has been opened for writing or a new file has been created [Open Group 2004]. If the O_CREAT
and O_EXCL
flags are used together, the open()
function fails when the file specified by file_name
already exists. To prevent an existing file from being opened and truncated, include the flags O_CREAT
and O_EXCL
when calling open()
.
...
Care should be observed when using O_EXCL
with remote file systems because it does not work with NFS version 2. NFS version 3 added support for O_EXCL
mode in open()
; see IETF RFC 1813 [Callaghan 1995], particularly the EXCLUSIVE
value to the mode
argument of CREATE
.
Moreover, the open()
function, as specified by the Open Group Base Specifications Issue 6 [Open Group 2004], does not include support for shared or exclusive locks. However, BSD systems support two additional flags that allow you to obtain these locks:
...
The TR 24731-1 tmpnam_s()
function generates a string that is a valid file name and that is not the same as the name of an existing file [ISO/IEC TR 24731-1:2007]. It is almost identical to the tmpnam()
function, except for an added maxsize
argument for the supplied buffer.
...
The mktemp()
function has been marked "LEGACY" in the Open Group Base Specifications Issue 6 [Open Group 2004]. The manual page for mktemp()
gives more detail:
...
The ISO/IEC TR 24731-1 function tmpfile_s()
creates a temporary binary file that is different from any other existing file and is automatically removed when it is closed or at program termination. If the program terminates abnormally, whether an open temporary file is removed is implementation-defined.
The file is opened for update with "wb+"
mode, which means "truncate to zero length or create binary file for update." To the extent that the underlying system supports the concepts, the file is opened with exclusive (nonshared) access and has a file permission that prevents other users on the system from accessing the file.
It should be possible to open at least TMP_MAX_S
temporary files during the lifetime of the program. (This limit may be shared with tmpnam_s()
.) The value of the macro TMP_MAX_S
is only required to be 25 [ISO/IEC TR 24731-1:2007].
TR 24731-1 notes the following regarding the use of tmpfile_s()
instead of tmpnam_s()
[ISO/IEC TR 24731-1:2007]:
After a program obtains a file name using the
tmpnam_s
function and before the program creates a file with that name, the possibility exists that someone else may create a file with that same name. To avoid this race condition, thetmpfile_s
function should be used instead oftmpnam_s
when possible. One situation that requires the use of thetmpnam_s
function is when the program needs to create a temporary directory rather than a temporary file.
...
The Open Group Base Specification Issue 6 [Open Group 2004] does not specify the permissions the file is created with, so these are implementation-defined. However, Issue 7 (POSIX.1-2008) specifies them as S_IRUSR|S_IWUSR
(0600) [Austin Group 2008].
This compliant solution invokes the user-defined function secure_dir()
} (such as the one defined in FIO15-C. Ensure that file operations are performed in a secure directory) to ensure the temporary file resides in a secure directory.
...
For GLIBC, versions 2.0.6 and earlier, the file is created with permissions 0666; for GLIBC, versions 2.0.7 and later, the file is created with permissions 0600. On NetBSD, the file is created with permissions 0600. This creates a security risk in that an attacker will have write access to the file immediately after creation. Consequently, programs need a private version of the mkstemp()
function in which this issue is known to be fixed.
In many older implementations, the name is a function of process ID and time, so it is possible for the attacker to predict the name and create a decoy in advance. FreeBSD changed the mk*temp()
family to eliminate the PID component of the file name and replace the entire field with base-62 encoded randomness. This raises the number of possible temporary files for the typical use of six X
's significantly, meaning that even mktemp()
with six X
's is reasonably (probabilistically) secure against guessing except under frequent usage [Kennaway 2000].
Exceptions
FIO43-EX1: The TR24731-1 tmpfile_s()
function can be used if all the targeted implementations create temporary files in secure directories.
...
Tool | Version | Checker | Description | ||||||
---|---|---|---|---|---|---|---|---|---|
Compass/ROSE |
|
| Can detect violations of this recommendation. Specifically, Rose reports use of | ||||||
| 489 S | Partially implemented. | |||||||
PRQA QA·CQA-C |
| Partially implemented |
...
ISO/IEC 9899:2011 Section 7.21.4.4, "The tmpnam
function," 7.21.4.3, "The tmpfile
function," and Section 7.21.5.3, "The fopen
function"
ISO/IEC PDTR 24772 "EWR Path traversal"
ISO/IEC TR 24731-1:2007 Section 6.5.1.2, "The tmpnam_s
function," Section 6.5.1.1, "The tmpfile_s
function," and Section 6.5.2.1, "The fopen_s
function"
MITRE CWE: CWE ID 379, "Creation of temporary file in directory with insecure permissions"
Bibliography
[Austin Group 2008]
[HP 2003]
[Kennaway 2000]
[Open Group 2004] mktemp()
, mkstemp()
, open()
[Seacord 2005a] Chapter 3, "Pointer Subterfuge," and Chapter 7, "File I/O"
[Viega 2003] Section 2.1, "Creating files for temporary use"
[Wheeler 2003] Chapter 7, "Structure Program Internals and Approach"
...