Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

...

Programs with elevated privileges may need to write files to directories owned by unprivileged users. One example would be a mail daemon that reads a mail message from one user and places it in a directory owned by another user. Any such program should have a security policy dictating what which users are trusted. For example, the mail daemon should trust only trust the user sending the message when gathering the mail to be sent , and then trust only trust the user receiving the message when delivering it.

...

Many operating systems support file links, including symbolic (soft) links, hard links, shortcuts, shadows, aliases, and junctions. Symbolic In POSIX, symbolic links can be created in POSIX using the ln -s command and hard links using the ln command. Hard links are indistinguishable from normal files on POSIX systems.

...

Performing operations on device files intended only for ordinary character or binary files can result in crashes and denial-of-service (DoS) attacks. For example, when Windows attempts to interpret a device name as a file resource, it performs an invalid resource access that usually results in a crash crash [Howard 2002].

Device files in POSIX can be a security risk when an attacker can trick a program into accessing them in an unauthorized way. For instance, if malicious programs can read or write to the /dev/kmem device file, they may be able to alter their own priority, user ID, or other attributes of their process, or they may simply crash the system. Similarly, access to disk devices, tape devices, network devices, and terminals being used by other processes can also lead to problems problems [Garfinkel 1996].

On Linux, it is possible to lock certain applications by attempting to read or write data on devices rather than files. Consider the following device path names:

Code Block
/dev/mouse
/dev/console
/dev/tty0
/dev/zero

A Web web browser that failed to check for these devices would allow an attacker to create a website with image tags such as <IMG src="file:///dev/mouse"> that would lock the user's mouse.

...

Unfortunately, an attacker could specify the name of a locked device or a first in, first out (FIFO) file, causing the program to hang when opening the file.

Noncompliant Code Example (

...

Regular File)

This noncompliant code example first checks that the file is a regular file before opening it.

...

This test can still be circumvented by a symbolic link. By default, the stat() builtin built-in function follows symbolic links and reads the file attributes of the final target of the link. The result is that the program may reference a file other than the one intended.

...

This noncompliant code example gets the file's information by calling lstat() rather than {[stat()}}. The lstat() system call does not follow symbolic links, and will provide it provides information about the link itself , rather than the file. So Consequently, this code will correctly identify identifies a symbolic link as ' not being a regular file'.

Code Block
bgColor#ffcccc
langperl
use Carp;
use Fcntl ':mode';

my $path = $ARGV[0]; # provided by user

# Check that file is regular
my $mode = (lstat($path))[2] or croak "Can't run lstat";
croak "Not a regular file" if (S_IFREG & $mode) == 0;

open( my $in, "<", $path) or croak "Can't open file";
# ... work with FILE and close it

This code is still vulnerable to a time-of-check, time-of-use (TOCTOU) race condition. For example, an attacker can replace the regular file with a file link or device file after the code has completed its checks but before it opens the file.

Noncompliant Code Example (

...

Check-

...

Use-

...

Check)

This noncompliant code example performs the necessary lstat() check and then opens the file , using the POSIX::open() function to obtain a file descriptor. After opening the file, it performs a second check to make sure that the file has not been moved and that the file opened is the same file that was checked. This check is accomplished using POSIX::fstat(), which returns the same information as lstat(), but operates on open file descriptors , rather than file names. This It does leave a race window open between the first check and the open , but subsequently detects if an attacker has changed the file during the race window. In both checks, the file's device and i-node attributes are examined. On POSIX systems, the device and i-node serve as a unique key for identifying files and , which is a more reliable indicator of the file's identity than its path name.

Code Block
bgColor#ffcccc
langperl
use Carp;
use Fcntl ':mode';
use POSIX;

my $path = $ARGV[0]; # provided by user

# Check that file is regular
my ($device, $inode, $mode, @rest) = lstat($path) or croak "Can't run lstat";
croak "Not a regular file" if (S_IFREG & $mode) == 0;

my $fd = POSIX::open($path, O_RDONLY) or croak "Can't open file";
# note: fd is a POSIX file descriptor, NOT a perl filehandle!

my ($fdevice, $finode, $fmode, @frest) = POSIX::fstat($fd) or croak "Can't run fstat";
croak "File has been tampered with" if $fdevice ne $device or $finode ne $inode;

open( my $in, "<&", $fd) or croak "Can't open file descriptor";
# ... work with FILE and close it

While Although this code goes to great lengths to prevent an attacker from successfully tricking it into opening the wrong file, it still has several vulnerabilities:

  • The TOCTOU race condition still exists between the first check and open. During this race window, an attacker can replace the regular file with a symbolic link or other nonregular file. The second check detects this race condition but does not eliminate it.
  • A system with hard links allows an attacker to construct a malicious file that is a hard link to a protected file. Hard links cannot be reliably detected by a program and can foil canonicalization attempts, which are prescribed by rule IDS00-PL. Canonicalize path names before validating them.

...

Because of the potential for race conditions and the inherent accessibility of shared directories by untrusted users, files must be operated on only by secure paths. A secure path is a directory that cannot be moved or deleted by untrusted users. Furthermore, its parent path must also be secure, as well as the , grandparent path, and so on , up to the root. Furthermore, , must also be secure, and if the path includes any symbolic links, both the link's target path and the path containing the link , must be secure paths. Because programs may run with reduced privileges and lack the facilities to construct a secure path, a program may need to abort if it determines that a given path is not secure.

...

When checking directories, it is important to traverse from the root directory to the leaf directory to avoid a dangerous race condition whereby an attacker who can write to at least one of the directories would rename and re-create a directory after the privilege verification of subdirectories but before the verification of the tampered directory. An attacker could use this race condition to fool the algorithm into falsely reporting that a path is secure.

...

On POSIX systems, disabling group and world write access to a directory prevents modification by anyone other than the owner of the directory and the system administrator; consequently, this function checks that each path lacks group or world write permissions. It also checks that a file is owned by either the user running the program or the system administrator. This is a reasonable definition of a secure path, but it could do other checks as well, such as the following:

  • checking group IDs
  • checking the file's sticky bit
  • checking that the file has only 1 one hard link
  • permitting a set of trusted users , in addition to the current user

This code is effective only on file systems that are fully compatible with POSIX file access permissions; it may behave incorrectly for file systems with other permission mechanisms such as AFS. It is designed to prevent untrusted users from creating race conditions based on the file system. It does not prevent race conditions in which both accesses to a file are performed by the user or the superuser.

The following compliant solution uses the is_secure_path() method to ensure that an attacker cannot tamper with the file to be opened and subsequently removed. Note that once the path name of a directory has been checked using is_secure_path(), all further file operations on that file must be performed using the same path. No race conditions are possible involving untrusted users, and so there is no need to perform any check after the open; the only remaining check necessary is the check that the file is a regular file.

...

FIO00:EX0: This recommendation does not apply to programs that run on a system with one user , or where all the users are trusted.

...

Performing operations on files in shared directories can result in ( DoS ) attacks. If the program has elevated privileges, privilege escalation exploits are possible.

Recommendation

Severity

Likelihood

Remediation Cost

Priority

Level

FIO01-PL

mediumMedium

unlikelyUnlikely

mediumMedium

P14P4

L3

Related Guidelines

...

...

The CERT Oracle Secure Coding Standard for Java: FIO00-J. Do not operate on files in shared directories]

...

...

Bibliography

[CPAN]POSIX
[Garfinkel 1996]Section 5.6, "Device files"
[Howard 2002]Chapter 11, "Canonical Representation Issues"
[Open Group 08]

...

...

...

 

...

Image Modified Image Modified Image Modified