Versions Compared

Key

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

External programs are commonly invoked to perform a function required by the overall system. This is a form of reuse and might even be considered a crude form of component-based software engineering. Command and argument injection vulnerabilities occur when an application fails to sanitize untrusted input and uses it in the execution of external programs.

The exec() builtin built-in function is the standard mechanism for executing system commands; it is a wrapper around the POSIX exec family of system calls. The system() builtin built-in function is similar to exec, but it takes a single string, whereas exec()takes a list. Finally  The qx operator, often represented by encasing a command in backquotes (``), can also be used to execute an arbitrary command. Finally, the open() command function can also execute commands in a subprocess and either send data to them or fetch data from them (but not both).

Command injection attacks cannot succeed unless a command interpreter is explicitly invoked. However, argument injection attacks can occur when arguments have spaces, double quotes, and so forth, or when they start with a - or / to indicate a switch.

This rule is a specific instance of rule IDS33-PL. Sanitize untrusted data passed across a trust boundary. Any string data that originates from outside the program's trust boundary must be sanitized before being executed as a command on the current platform.

...

This noncompliant code example tries to list a directory specified by the user. It safely uses the 3three-argument open() command, as required by IDS31-PL. Do not use the two-argument form of open().

Code Block
bgColor#ffcccc
langperl
use Carp;

my $dir = $ARGV[0];
open( my $listing, "-|", "ls -F $dir") or croak "error executing command: stopped";
while (<$listing>) {
  print "Result: $_";
}
close( $listing);

...

But it can also have unintended consequences, as in this case, if an attacker injects an arbitrary command to be executed by the call to open():

...

Code Block
bgColor#ccccff
langperl
use Carp;

my $file;
my $dir = $ARGV[0];
croak "Argument contains unsanitary characters, stopped" if ($dir =~ m|[^-A-Za-z0-9_/.~]|);
open( my $listing, "-|", "ls -F $dir") or croak "error executing command: stopped";
while (<$listing>) {
  print "Result: $_";
}
close( $listing);

This code will properly reject rejects shell commands:

Code Block
% ./example.pl "dummy ; echo bad"
Argument contains unsanitary characters, stopped at ./example.pl line 8
% 

However, this code will also reject rejects valid directories if they contain characters not in the white list whitelist regex.

Compliant Solution (Shell Avoidance)

This compliant solution again sanitizes the untrusted user input. However, it uses the multi-arg form of open().

Code Block
bgColor#ccccff
langperl
my $file;
my $dir = $ARGV[0];
croak "Argument contains unsanitary characters, stopped" if ($dir =~ m|[^-A-Za-z0-9_/.~]|);
open( my $listing, "-|", "ls", "-F", $dir) or croak "error executing command: stopped";
while (<$listing>) {
  print "Result: $_";
}
close( $listing);

The perlfunc manpages states, regarding all but the first two arguments to open():

If there is only one scalar argument, the argument is checked for shell metacharacters, and if there are any, the entire argument is passed to the system's command shell for parsing (this is "/bin/sh -c" on Unix platforms, but varies on other platforms). If there are no shell metacharacters in the argument, it is split into words and passed directly to "execvp," which is more efficient.

So this form of open() is preferable if your platform's shell might be set up incorrectly or maliciously.

Compliant Solution (Restricted Choice)

This compliant solution prevents command injection by passing only trusted strings to open(). While the The user has control over which string is used , the user but cannot provide string data directly to open().

Code Block
bgColor#ccccff
langperl
use Carp;

my %choices = (BIN => "~/bin",
               LIB => "~/lib",
               SRC => "~/src");
my $choice = $choices{$ARGV[0]};
croak "Invalid argument, stopped" if (!defined $choice);
open( my $listing, "-|", "ls -F $choice") or croak "error executing command: stopped";
while (<$listing>) {
  print "Result: $_";
}
close( $listing);

This compliant solution hard - codes the directories that may be listed.

...

US-CERT Vulnerability #583020  describes Perl code that invoked the system() builting built-ig function without sanitizing its argument:

...

An attacker who could control the arguments to the do() subroutine could cause the code to invoke arbitrary shell commands. This code also violates DCL31-PL. Do not overload reserved keywords or subroutines.

Compliant Solution (VU#583020)

...

Code Block
bgColor#ccccff
langperl
sub do {
    shift;
    $command = shift;
    $command =~ /([\w])/;
    $command = $1;
    $do_call = "xmms -" . $command;
    system $do_call;
    return $do_call;
  }

This code still violates DCL31-PL. Do not overload reserved keywords or subroutines; it is shown here for historical accuracy.

Risk Assessment

Using deprecated or obsolete classes or methods in program code can lead to erroneous behavior.

Recommendation

Severity

Likelihood

Remediation Cost

Priority

Level

IDS34-PL

highHigh

probableProbable

mediumMedium

P18P12

L1

Automated Detection

Tool

Diagnostic

Taint modeInsecure dependency in (system|piped open)

Related Guidelines

...

...

...

...

...

...

...

...

...

...

Bibliography

[

...

...

...

 

 

...

Image Added Image Added Image Added'Image Removed      03. Expressions      EXP30-PL. Do not use deprecated or obsolete functions