...
Code Block | ||
---|---|---|
| ||
... FILE *file_ptr; result = tmpfile_s(&file_ptr); if (result != 0) { /* Handle Error */ } t_file = fopen_s(temp_file_name, "wb+"); if (!t_file) { /* Handle Error */ } ... |
This example needs to be checked
Wiki Markup |
---|
This solution is also non-compliant because it violates \[[FIO32-C|FIO32-C. Temporary file names must be unique when the file is created]\] and \[[FI042-C|FI042-C. Temporary files must be removed before the program exits]\]. |
Non-Compliant Code Example
...
: mktemp(
...
)
The POSIX function {{mktemp() is similar to tmpnam()
save it allows the user to specify a template to use for the unique file name. Like tmpnam()
, mktemp()
may introduce a TOCTOU race condition. The following example demonstrates this}}takes a given file name template and overwrites a portion of it to create a file name.
The template may be any file name with some number of 'X's appended to it, for example /tmp/temp.XXXXXX
. The trailing 'X's are replaced with the current process number and/or a unique letter combination. The number of unique file names mktemp() can return depends on the number of 'X's provided.
Code Block | ||
---|---|---|
| ||
... FILE *temp_ptr; char temp_name[] = "/tmp/temp-XXXXXX"; if (mktemp(temp_name) == NULL) { /* Handle Error */ } temp_ptr = fopen(temp_name,"w+"); if (temp_ptr == NULL) { /* Handle Error */ } ... |
...
Wiki Markup |
---|
This solution is also non-compliant because it violates \[[FIO32-C|FIO32-C. Temporary file names must be unique when the file is created]\] and \[[FI042-C|FI042-C. Temporary files must be removed before the program exits]\]. |
Compliant Solution: (POSIX)
A reasonably secure solution for generating random file names in UNIX is to call use the mkstemp()
function as follows:. The mkstemp()
function is available on systems that support the Open Group Base Specifications Issue 4, Version 2 or later.
A call to mkstemp()
replaces the six Xs in the template string with six randomly-selected characters:
Code Block |
---|
char template[] = "/tmp/fileXXXXXX";
if ((fd = mkstemp(template)) == -1) {
err(1, "random file");
}
|
The mkstemp()
algorithm for selecting file names has proven to be immune to attacks.
Code Block | ||
---|---|---|
| ||
char sfn[15] = "/tmp/ed.XXXXXX"; FILE *sfp; int fd = -1; if ((fd = mkstemp(sfn)) == -1 || (sfp = fdopen(fd, "w+")) == NULL) { if (fd != -1) { unlink(sfn); close(fd); } fprintf(stderr, "%s: %s\n", sfn, strerror(errno)); return (NULL); } |
Implementation Details
In many older implementations, the name is a function of process ID and time--so it is possible for the attacker to guess it and create a decoy in advance. FreeBSD has recently changed the mk*temp()
family to get rid of the PID component of the filename and replace the entire thing with base-62 encoded randomness. This raises the number of possible temporary files for the "default" usage of 6 X's significantly, meaning that even mktemp()
with 6 X's is reasonably (probabilistically) secure against guessing, except under very frequent usage Kennaway 00.
Risk Assessment
A protected system file to which the symbolic link points can be overwritten when a vulnerable program is executed.
Rule | Severity | Likelihood | Remediation Cost | Priority | Level |
---|---|---|---|---|---|
FIO32-C | 3 2 (high) | 2 (probable) | 1 2 (medium) | P6 | L2 |
References
- ISO/IEC 9899-1999 Sections 7.19.4.3 The tmpfile function, 7.19.4.4 The tmpnam function
- ISO/IEC TR 24731-2006 Section 6.5.1.1 The tmpfile_s function