File operations should be performed in a secure directory. In most cases, a secure directory is a directory in which no one other than the user, or possibly the administrator, has the ability to create, rename, delete, or otherwise manipulate files. (Other users may read or search the directory but generally may not modify the directory's contents in any way.) Also, other users must not be able to delete or rename files in the parent of the secure directory and all higher directories, although creating new files or deleting or renaming files they own is permissible.
Performing file operations in a secure directory eliminates the possibility that an attacker might tamper with the files or file system to exploit a file system vulnerability in a program. These vulnerabilities often exist because there is a loose binding between the file name and the actual file. (See FIO01-C. Be careful using functions that use file names for identification.) In some cases, file operations can be performed securely anywhere. In other cases, the only way to ensure secure file operations is to perform the operation within a secure directory.
Ensuring that file systems are configured in a safe manner is typically a system administration function. However, programs can often check that a file system is securely configured before performing file operations that may lead to security vulnerabilities if the system is misconfigured. There is a slight possibility that file systems will be reconfigured in an insecure manner while a process is running and after the check has been made. As a result, it is always advisable to implement your code in a secure manner (that is, consistent with the other rules and recommendations in this section) even when running in a secure directory.
Noncompliant Code Example
In this noncompliant code example, the file identified by
file_name is opened, processed, closed, and removed:
An attacker can replace the file object identified by
file_name with a link to an arbitrary file before the call to
fopen(). It is also possible that the file object identified by
file_name in the call to
remove() is not the same file object identified by
file_name in the call to
fopen(). If the file is not in a secure directory, for example,
/tmp/app/tmpdir/passwd, then an attacker can manipulate the location of the file as follows:
Not much can be done programmatically to ensure the file removed is the same file that was opened, processed, and closed, except to make sure that the file is opened in a secure directory with privileges that would prevent the file from being manipulated by an untrusted user.
Compliant Solution (POSIX)
This sample implementation of the function
secure_dir() ensures that the directory
fullpath and all directories above it are owned by either the user or the superuser and that other users do not have write access to the directories. When checking directories, it is important to traverse from the root to the leaf to avoid a dangerous race condition in which an attacker who has privileges to at least one of the directories can rename and re-create a directory after the privilege verification.
fullpath need not be canonicalized (see FIO02-C. Canonicalize path names originating from tainted sources). If the path contains a symbolic link, this routine recursively invokes itself on the linked-to directory and ensures it is also secure. A symbolically linked directory may be secure if both its source and linked-to directory are secure.
Note that this function is effective only on file systems that are fully compatible with UNIX permissions, and it may not behave normally for file systems with other permission mechanisms, such as AFS (Andrew File System).
This compliant solution uses the
secure_dir() function to ensure that an attacker may not tamper with the file to be opened and subsequently removed. Note that once the path name of a directory has been checked using
secure_dir(), all further file operations on that directory must be performed using the same path.
Failing to perform file I/O operations in a secure directory that cannot otherwise be securely performed can result in a broad range of file system vulnerabilities.
|SEI CERT C++ Coding Standard
|VOID FIO15-CPP. Ensure that file operations are performed in a secure directory
|CWE-379, Creation of temporary file in directory with insecure permissions
CWE-552, Files or directories accessible to external parties
|[IEEE Std 1003.1:2013]
|XSH, System Interfaces,
XSH, System Interfaces,
|Section 2.4, "Determining Whether a Directory Is Secure"