You are viewing an old version of this page. View the current version.

Compare with Current View Page History

Version 1 Next »

A file path is a string that indicates how to find a file, starting from a particular directory. If a path begins with the root directory, or with a root volume (eg C: in Windows), it is an absolute path, otherwise, it is a relative path.

Absolute or relative path names may contain file links such as symbolic (soft) links, hard links, short cuts, shadows, aliases, and junctions. These file links must be fully resolved before any file validation operations are performed. For example, the final target of a symbolic link called trace might be the path name /home/system/trace. Path names may also contain special file names that make validation difficult:

  • "." refers to the directory itself.
  • Inside a directory, the special file name ".." refers to the directory's parent directory.

In addition to these specific issues, there are a wide variety of operating system-specific and file system-specific naming conventions that make validation difficult.

The process of canonicalizing file names makes it easier to validate a path name. More than one path name can refer to a single directory or file. Furthermore, the textual representation of a path name may yield little or no information regarding the directory or file to which it refers. Consequently, all path names must be fully resolved or canonicalized before validation. Because the canonical form can vary between operating systems and file systems, it is best to use operating-system-specific mechanisms for canonicalization; however this option is often not available.

For example, validation may be necessary when attempting to restrict user access to files within a particular directory or otherwise make security decisions based on the name of a file name or path name. Frequently, these restrictions can be circumvented by an attacker by exploiting a directory traversal or path equivalence vulnerability. A directory traversal vulnerability allows an I/O operation to escape a specified operating directory. A path equivalence vulnerability occurs when an attacker provides a different but equivalent name for a resource to bypass security checks.

Canonicalization contains an inherent race window between the time the program obtains the canonical path name and the time it opens the file. While the canonical path name is being validated, the file system may have been modified and the canonical path name may no longer reference the original valid file. Fortunately, this race condition can be easily mitigated. A path name that is a secure path is immune to race windows and other attempts to confuse the program by an untrusted user. See rule FIO01-PL. Do not operate on files that can be modified by untrusted users for more information on secure paths.

Noncompliant Code Example (POSIX)

This noncompliant code example allows the user to specify a file inside the /img directory for the program to work with. Due to its lack of checks, the user can specify files outside the intended directory by entering an argument that contains ../ sequences and consequently violates the intended security policies of the program.

sub work_with_image {
  my ($image_file) = @_; # untrusted
  open( my $image, "<", "/img/$image_file") or croak "Can't open image file";
  # ...
}

Noncompliant Code Example (POSIX, File::PathConvert)

This noncompliant code example attempts to enforce that the file specified still lives within the /img directory. However it is using the File::PathConvert module, which has been deprecated.

use File::PathConvert qw(realpath $resolved);

sub work_with_image {
  my ($image_file) = @_; # untrusted
  $image_file = realpath("/img/$image_file") || croak "Resolution stopped at $resolved";
  open( my $image, "<", $image_file) or croak "Can't open $image_file";
  # ...
}

According to the CPAN entry for File::PathConvert:

There are several known bugs, and it is not being actively
maintained since all functionality is now available in
modules (Cwd.pm and File::Spec) bundled in every Perl
distribution of recent vintage. This version is provided to
fix a few bugs and to get the word out about the
deprecation.

Compliant Solution (POSIX, Cwd)

This compliant solution obtains the file name from the untrusted user input, and canonicalizes it using Perl's Cwd module, which is part of the standard Perl distribution.

use Cwd 'abs_path';

sub work_with_image {
  my ($image_file) = @_; # untrusted
  $image_file = abs_path("/img/$image_file");
  $filename = abs_path( $filename);
  open( my $image, "<", $image_file) or croak "Can't open $image_file";
  # ...
}

Noncompliant Code Example

This noncompliant code example accepts a file path as a command-line argument and uses the is_secure_path() subroutine defined in rule FIO01-PL. Do not operate on files that can be modified by untrusted users. This ensures that the file is in a secure directory. The validate_path() routine performs string-based validation on the path name. This could include checking for such things as:

  • the file lives in the user's home directory
  • the file ends with the proper suffix, such as .html.
  • the file does not contain 'weird' characters such as spaces.
my $filename = $ENV{"HOME"} . $DIR_SEP . $ARGV[0];
# $DIR_SEP = / on POSIX or \ on Windows
croak "Not a secure path" if !is_secure_path( $filename);
croak "Invalid path" if !validate_path( $filename);

However, this code neither resolves file links nor eliminates equivalence errors. Consequently, the validation routine may pass on the pathname given, whereas the pathname might resolve to a file that the validation routine would fail on. For instance, a pathname that starts with /home/person might resolve to a file that lives outside /home/person, foiling a validation routine that ensures that the file lives in the person's home directory.

Compliant Solution (POSIX)

This compliant solution uses the Cwd module to obtain the file's canonical path before performing any validation. This guarantees that any string-based operations the validation may perform on the path is performed on the canonical path, and can therefero not be foiled by symbolic links or . or .. in the path.

Furthermore, canonicalization is performed after the file has been verified to live in a secure path. This prevents attackers from conducting TOCTOU attacks against the program during the abs_path() call, or the validation, or any subsequent operations on the path.

use Cwd 'abs_path';

my $DIR_SEP = "/";

my $filename = $ENV{"HOME"} . $DIR_SEP . $ARGV[0];
croak "Not a secure path" if !is_secure_path( $filename);
$filename = abs_path( $filename);
croak "Invalid path" if !validate_path( $filename);

Compliant Solution (Windows)

Producing canonical file names for Windows operating systems is extremely complex and beyond the scope of this standard. The best advice is to try to avoid making decisions based on a path, directory, or file name [[Howard 2002|Bibliography#Howard 2002]. Alternatively, use operating-system-based mechanisms, such as access control lists (ACLs) or other authorization techniques.

Risk Assessment

Recommendation

Severity

Likelihood

Remediation Cost

Priority

Level

IDS00-PL

medium

unlikely

medium

P4

L3

Related Guidelines

CERT C Secure Coding Standard: FIO02-C. Canonicalize path names originating from untrusted sources

The CERT Oracle Secure Coding Standard for Java: MET02-J. Do not use deprecated or obsolete classes or methods

CERT C++ Secure Coding Standard: FIO02-CPP. Canonicalize path names originating from untrusted sources

Bibliography

[Wall 2011] Cwd
[CPAN] Slaymaker, Barrie. File::PathConvert, Müller, Steffen. File::Spec
Vulnerability Note VU#764027: "zml.cgi does not adequately validate user input thereby allowing directory traversal"
Vulnerability Note VU#806091: "Mike Spice's My Calendar does not adequately validate user input"


      03. Expressions      EXP30-PL. Do not use deprecated or obsolete functions

  • No labels