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 e.g., 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 cutsshortcuts, 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:
...
In addition to these specific issues, there are a wide variety of operating system-specific system–specific and file system-specific 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 among operating systems and file systems, it is best to use operating -system-specific 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, an attacker can circumvent 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 by an untrusted user 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 Because of 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.
Code Block | ||||
---|---|---|---|---|
| ||||
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.
Code Block | ||||
---|---|---|---|---|
| ||||
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"; if ($image_file !~ m|/img/|) { croak "Image file not in /img"; } open( my $image, "<", $image_file) or croak "Can't open $image_file"; # ... } |
...
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.
Code Block | ||||
---|---|---|---|---|
| ||||
use Cwd 'abs_path'; sub work_with_image { my ($image_file) = @_; # untrusted $image_file = abs_path("/img/$image_file"); $filename = abs_path( $filename);if ($image_file !~ m|/img/|) { croak "Image file not in /img"; } 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 :that
- 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.
...
However, this code neither resolves file links nor eliminates equivalence errors. Consequently, the validation routine may pass on the pathname path name given, whereas the pathname path name might resolve to a file that the validation routine would fail on. For instance, a pathname path name 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 are performed on the canonical path , and can therefero not therefore cannot 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 time-of-check, time-of-use (TOCTOU) attacks against the program during the abs_path()
call, or the validation, or any subsequent operations on the path.
Code Block | ||||
---|---|---|---|---|
| ||||
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 the basis of a path, directory, or file name [ [Howard 2002|Bibliography#Howard 2002]. Alternatively, use operating -system-based 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 |
Automated Detection
Tool | Diagnostic | Notes |
---|---|---|
Taint mode | Insecure dependency in .*open | Detects only files open for writing. |
Related Guidelines
...
...
FIO02-C. Canonicalize path names originating from tainted sources | |
SEI CERT C++ Coding Standard | VOID FIO02-CPP. Canonicalize path names originating from untrusted sources |
...
...
...
Bibliography
[ |
...
CPAN] |
...
...
Slaymaker, Barrie |
...
...
; Müller, Steffen |
...
...
[Howard 2002] | Chapter 11, "Canonical Representation Issues" |
[VU#764027] | zml.cgi does not adequately validate user input thereby allowing directory traversal |
...
...
...
" 03. Expressions EXP30-PL. Do not use deprecated or obsolete functions