Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.
Comment: FIO46->FIO43

...

None of these functions are without problems. The best advice is not to create temporary files in shared directories. In cases where it is absolutely necessary to do so, however, the tmpfile_s() and mkstemp() provide the most secure solutions.

Unique and Unpredictable file names

Programs that create files in shared directories may be exploited to overwrite protected files. For example, 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 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, the protected file referenced by the symbolic link can be overwritten when the program is executed. To ensure that the name of the temporary file does not conflict with a preexisting file and that it cannot be guessed before the program is run, temporary files must be created with unique and unpredictable file names.

Exclusive Access

Wiki Markup
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 \[[Seacord 05|AA. C References#Seacord 05]\] Chapter 7).

...

  1. mandatory locking works only on local file systems and does not extend to network file systems (NFS and AFS)
  2. file systems must be mounted with support for mandatory locking, and this is disabled by default
  3. locking relies on the group ID bit that can be turned off by another process (thereby defeating the lock).

Removal before termination

It is important to remember to cleanup in order to allow filenames 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 tmp cleaner utilities are widely used. These tmp cleaners are invoked manually by a system administrator or run as a cron daemon to sweep temporary directories and remove old files. These tmp cleaners are themselves vulnerable to file-based exploits, and often require the use of shared directories (see: FIO15-A. Do not create temporary files in shared directories). However, during normal operation, it is the responsibility of the program to ensure that temporary files are either removed explicitly, or through the use of library routines such as tmpfile_s which guarantee their removal upon program termination.

Non-Compliant Code Example: fopen()/open() with tmpnam()

The following non-compliant code creates a file with some hard coded file_name (presumably in a shared directory such as /tmp or C:\Temp).

...

  • O_SHLOCK Atomically obtain a shared lock.
  • O_EXLOCK Atomically obtain an exclusive lock.

Non-Compliant Code Example: tmpnam_s() (ISO/IEC TR 24731-1)

Wiki Markup
The TR 24731-1 {{tmpnam_s()}} function generates a string that is a valid filename and that is not the same as the name of an existing file \[[ISO/IEC TR 24731-1-2007|AA. C References#SO/IEC TR 24731-1-2007]\]. It is almost identical to the {{tmpnam}} function above except with an added {{maxsize}} argument for the supplied buffer.

...

Code Block
bgColor#FFCCCC
char file_name[L_tmpnam_s];
int fd;

if (tmpnam_s(file_name, L_tmpnam_s) != 0) {
  /* Handle Error */
}

/* A TOCTOU race condition exists here */

if((fd = open(file_name, O_WRONLY | O_CREAT | O_EXCL | O_TRUNC, 0600)) < 0) {
   /* Handle Error */
}

Implementation Details

For Microsoft Visual Studio 2005, the name generated by tmpnam_s consists of a program-generated filename and, after the first call to tmpnam_s(), a file extension of sequential numbers in base 32 (.1-.1vvvvvu, when TMP_MAX_S in stdio.h is INT_MAX).

Non-Compliant Code Example: mktemp()/open() (POSIX)

The POSIX function mktemp() takes a given filename template and overwrites a portion of it to create a filename. The template may be any filename with some number of Xs appended to it (for example, /tmp/temp.XXXXXX). The trailing Xs are replaced with the current process number and/or a unique letter combination. The number of unique filenames mktemp() can return depends on the number of Xs provided.

...

Never use mktemp(). Some implementations follow BSD 4.3 and replace XXXXXX by the current process id and a single letter, so that at most 26 different names can be returned. Since on the one hand the names are easy to guess, and on the other hand there is a race between testing whether the name exists and opening the file, every use of mktemp() is a security risk. The race is avoided by mkstemp(3).

Non-Compliant Code Example: tmpfile()

The C99 tmpfile() function creates a temporary binary file that is different from any other existing file and that is automatically removed when it is closed or at program termination.

...

Code Block
bgColor#FFCCCC
FILE* fp;

if (!(fp = tmpfile())) {
  /* Handle Error */
}

Compliant Solution: mkstemp() (POSIX)

A reasonably secure solution for generating random file names is to use the mkstemp() function. The mkstemp() function is available on systems that support the Open Group Base Specifications Issue 4, Version 2 or later.

...

Wiki Markup
The Open Group Base Specification Issue 6 \[[Open Group 04|AA. C References#Open Group 04]\] does not specify the permissions the file is created with, so these are [implementation-defined|BB. Definitions#implementation-defined behavior]. However, Issue 7 (that is, POSIX.1-2008) specifies them as {{S_IRUSR\|S_IWUSR}} (0600).

Implementation Details

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.

Wiki Markup
In many older [implementations|BB. Definitions#implementation], 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 has recently changed the {{mk*temp()}} family to eliminate the PID component of the filename and replace the entire field with base-62 encoded randomness.  This raises the number of possible temporary files for the typical use of 6 Xs significantly, meaning that even {{mktemp()}} with 6 Xs is reasonably (probabilistically) secure against guessing, except under frequent usage \[[Kennaway 00|AA. C References#Kennaway 00]\] .

Compliant Solution: tmpfile_s() (ISO/IEC TR 24731-1 )

The ISO/IEC TR 24731-1 function tmpfile_s() creates a temporary binary file that is different from any other existing file and that 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.

...

Code Block
bgColor#ccccff
if (tmpfile_s(&fp)) {
  /* Handle Error */
}

Risk Assessment

Failure to create unique, unpredictable temporary file names can make it possible for an attacker to access or modify privileged files.

Rule

Severity

Likelihood

Remediation Cost

Priority

Level

FIO46 FIO43-C

3 (high)

2 (probable)

1 (high)

P6

L2

Related Vulnerabilities

Search for vulnerabilities resulting from the violation of this rule on the CERT website.

References

Wiki Markup
\[[ISO/IEC 9899-1999|AA. C References#ISO/IEC 9899-1999]\] Sections 7.19.4.4, "The {{tmpnam}} function," 7.19.4.3, "The {{tmpfile}} function," and 7.19.5.3, "The {{fopen}} function"
\[[ISO/IEC PDTR 24772|AA. C References#ISO/IEC PDTR 24772]\] "EWR Path Traversal"
\[[ISO/IEC TR 24731-1-2007|AA. C References#ISO/IEC TR 24731-1-2007]\] Sections 6.5.1.2, "The {{tmpnam_s}} function," 6.5.1.1, "The {{tmpfile_s}} function," and 6.5.2.1, "The {{fopen_s}} function"
\[[Open Group 04|AA. C References#Open Group 04]\] [{{mktemp()}}|http://www.opengroup.org/onlinepubs/000095399/functions/mktemp.html], [{{mkstemp()}}|http://www.opengroup.org/onlinepubs/009695399/functions/mkstemp.html], [{{open()}}|http://www.opengroup.org/onlinepubs/009695399/functions/open.html]
\[[Seacord 05a|AA. C References#Seacord 05a]\] Chapter 3, "File I/O"
\[[Wheeler 03|AA. C References#Wheeler 03]\] [Chapter 7, "Structure Program Internals and Approach"|http://www.dwheeler.com/secure-programs/Secure-Programs-HOWTO/avoid-race.html#TEMPORARY-FILES]
\[[Viega 03|AA. C References#Viega 03]\] Section 2.1, "Creating Files for Temporary Use"
\[[Kennaway 00|AA. C References#Kennaway 00]\]
\[[HP 03|AA. C References#HP 03]\]

...

FIO16FIO42-A. Avoid reopening a file streamC. Ensure files are properly closed when they are no longer needed      09. Input Output (FIO)       10. Environment (ENV) Image Added