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

Compare with Current View Page History

« Previous Version 16 Next »

Never call any formatted I/O function with a format string containing user input.

An attacker who can fully or partially control the contents of a format string can crash the Perl interpreter, or cause a denial of service. She can also modify values, perhaps by using the %n|| conversion specifier, and use these values to divert control flow. Their capabilities are not as strong as in C [Seacord 2005]; nonetheless the danger is sufficiently great that the formatted output functions {{sprintf() and printf() should never be passed unsanitized format strings.

Noncompliant Code Example

This noncompliant code example tries to authenticate a user by having the user supply a password and granting access only if the password is correct.

sub validate_password {
  my ($prompt, $password) = @_;
  my $is_ok = ($password eq "goodpass");
  printf "$prompt: Password ok? %d\n", $is_ok;
  return $is_ok;
};

my $host = `hostname`;
chop($host);
my $prompt = "$ENV{USER}\@$host";
if (validate_password( $prompt, $ARGV[0])) {
  print "$prompt: access granted\n";
} else {
  print "$prompt: access denied\n";
};

The program works as expected as long as the user name and host name are benign:

user@host:~$ ./authenticate.pl goodpass
user@host: Password ok? 1
user@host: access granted
user@host:~$ ./authenticate.pl badpass
user@host: Password ok? 0
user@host: access denied
user@host:~$ 

However, the program can be foiled by a malicious user name:

user@host:~$ env USER=user%n ./authenticate.pl badpass
user%n@host: Password ok? 0
user%n@host: access granted
user@host:~$ 

In this invocation, the malicious user name user%n was incomprorated into the $prompt string. When fed to the printf() call inside validate_password(), the %n instructed Perl to fill the first format string argument with the number of characters printed. This caused Perl to set the $is_ok variable to 4. Since it is now nonzero, the program incorrectly grants access to the user.

Compliant Solution (print())

This compliant solution avoids the use of printf(), since print() provides sufficient functionality.

sub validate_password {
  my ($prompt, $password) = @_;
  my $is_ok = ($password eq "goodpass");
  print "$prompt: Password ok? $is_ok\n";
  return $is_ok;
};

# ...

Risk Assessment

Recommendation

Severity

Likelihood

Remediation Cost

Priority

Level

IDS30-PL

high

probable

low

P18

L1

Automated Detection

Perl's Taint mode provides partial detection of unsanitized input in format strings.

Perl's warnings can detect if a call to printf() or sprintf() contains the wrong number of format string arguments.

Related Guidelines

CERT C Secure Coding Standard: FIO30-C. Exclude user input from format strings

CERT C++ Secure Coding Standard: FIO30-CPP. Exclude user input from format strings

The CERT Oracle Secure Coding Standard for Java: IDS06-J. Exclude user input from format strings

MITRE CWE: CWE-134, "Uncontrolled format string"

Bibliography

[Christey 2005] Format string vulnerabilities in Perl programs
[Seacord 2005] Chapter 6, "Formatted Output"
[VU#948385] "Perl contains an integer sign error in format string processing"
[Wall 2011] perlfunc


  • No labels