Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.
Comment: merging in TMP32 bit by bit

...

These Windows file-locking mechanisms are called mandatory locks because every process attempting access to a locked file region is subject to the restriction. Linux implements both mandatory locks and advisory locks. An advisory lock is not enforced by the operating system, which severely diminishes its value from a security perspective. Unfortunately, the mandatory file lock in Linux is also largely impractical for the following reasons: (a)

  1. mandatory locking works only on local file systems and does not extend to network file systems (NFS and AFS)

...

  1. file systems must be mounted with support for mandatory locking, and this is disabled by default

...

  1. 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: TMP00-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() and tmpnam()

The following non-compliant code creates a file with some _file in the /tmp directory. The name is hard coded and consequently is neither unique nor unpredictablehard coded file_name (presumably in a shared directory such as /tmp).

Code Block
bgColor#FFCCCC
FILEchar *fp file_name = fopen("/tmp/some_file"/* hard coded string */;
FILE *fp = fopen(file_name, "w");

If /tmp/some_file already exists, then that file is opened and truncated. If /tmp/some_file is a symbolic link, then the Clearly, since the name is hard coded and consequently neither unique nor unpredictable, an attacker need only place a symbolic link in lieu of the file and the target file referenced by the link is truncated.

To exploit this coding error, an attacker need only create a symbolic link called /tmp/some_file before execution of this statement.

Non-Compliant Code Example: open()

opened and truncated.

Wiki Markup
The {{fopen()}} function does not indicate whether an existing file has been opened for writing or a new file has been created. However, the {{openfollowing non-compliant code attempts to remedy the problem by generating the filename at runtime using {{tmpnam()}}.  The C99 {{tmpnam()}} function asgenerates defineda instring thethat Openis Groupa Basevalid Specificationsfilename Issueand 6 \[[Open Group 04that is not the same as the name of an existing file \[[ISO/IEC 9899-1999|AA. C References#Open Group 04References#ISO/IEC 9899-1999]\]. providesFiles suchcreated ausing mechanism.strings generated Ifby the {{O_CREATtmpnam()}} 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()}}function are temporary in that their names should not collide with those generated by conventional naming rules for the [implementation|BB. Definitions#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.

Code Block
bgColor#FFCCCC
int fd = open("/tmp/some_file", O_WRONLY | O_CREAT | O_EXCL | O_TRUNC, 0600);
char *file_name[L_tmpnam];
FILE* fp;

if (tmpnam(file_name) == NULL || (fp = fopen(file_name, "wb+")) == NULL) {
   /* Handle Error */
}

Since neither does tmpnam() guarantee a unique name, nor does fopen() provide a facility for an exclusive open, this code is still vulnerable to the exploit aboveThis call to open() fails whenever /tmp/some_file already exists, including when it is a symbolic link. This is secure, but a temporary file is presumably still required. One approach that can be used with open() is to generate random filenames and attempt to open() each until a unique name is discovered. Luckily, there are predefined functions that perform this function.

Wiki Markup
Care should be observed whenThe next code sample attempts to remedy the problem by using {{O_EXCLopen()}}, withdefined remotein filethe systems,Open asGroup itBase doesSpecifications notIssue work with NFS version 2. NFS version 3 added support for {{O_EXCL}} mode in {{open()}}; see IETF RFC 1813 \[[Callaghan 95|AA. C References#Callaghan 95]\], in particular the {{EXCLUSIVE}} value to the {{mode}} argument of {{CREATE}}.

Non-Compliant Code Example: tmpnam()

Wiki Markup
The C99 {{tmpnam6 \[[Open Group 04|AA. C References#Open Group 04]\], and providing a mechanism to indicate whether an existing file has been opened for writing or a new file has been created. If the {{O_CREAT}} and {{O_EXCL}} flags are used together, the {{open()}} function generatesfails awhen stringthe thatfile isspecified a valid filename and that is not the same as the name of an existing file \[[ISO/IEC 9899-1999|AA. C References#ISO/IEC 9899-1999]\]. 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|BB. Definitions#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.  If the argument is not a null pointer, it is assumed to point to an array of at least {{L_tmpnam}} chars; the {{tmpnam()}} function writes its result in that array and returns the argument as its value.

...

bgColor#FFCCCC

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()}}.

Code Block
bgColor#FFCCCC

char *file_name[L_tmpnam];
int fd;

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

This call to open() fails whenever file_name already exists, including when it is a symbolic link. This is secure, but a temporary file is presumably still required. Unfortunately, the method used by tmpnam() to generate filenames is not guaranteed to be unpredictable, which leaves room for an attacker to guess the filename ahead of time.

Wiki Markup
Care should be observed when using {{O_EXCL}} with remote file systems, as it does not work with NFS version 2. NFS version 3 added support for {{O_EXCL}} mode in {{open()}}; see IETF RFC 1813 \[[Callaghan 95|AA. C References#Callaghan 95]\], in particular the {{EXCLUSIVE}} value to the {{mode}} argument of {{CREATE}}.

...

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

...