...
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.
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.
...
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); 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:
...
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.
...
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 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
...
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"
...