Perl / perl5

🐪 The Perl programming language
https://dev.perl.org/perl5/
Other
1.99k stars 559 forks source link

Consultation required on possible Perl security issue #5968

Closed p5pRT closed 21 years ago

p5pRT commented 22 years ago

Migrated from rt.perl.org#17698 (status was 'resolved')

Searchable as RT17698$

p5pRT commented 22 years ago

From coley@linus.mitre.org

Hello\,

I am a computer security researcher. I have recently found some ways that programmers could misuse certain Perl functions with potential security implications (no\, not the same old open() or system() problems).

However\, there is a possibility that there are security-related bugs in Perl itself\, including a potential bug in the taint checker. I would like to consult with someone to confirm this issue.

Because I don't know who is going to see this email\, I am omitting details until I hear from someone. However\, one vulnerability researcher has already alluded to the type of problem I am discussing\, so the issue is at least partially public.

The Responsible Vulnerability Disclosure Process guidelines [1] suggest that a vendor or developer should respond to an initial security vulnerability report within 7 days. I hope to hear from you within that time frame.

Regards\,

Steve Christey Principal Information Security Engineer The MITRE Corporation

[1] http​://www.ietf.org/internet-drafts/draft-christey-wysopal-vuln-disclosure-00.txt

p5pRT commented 22 years ago

From @schwern

On Tue\, Oct 01\, 2002 at 03​:52​:40AM -0000\, Steve Christey wrote​:

However\, there is a possibility that there are security-related bugs in Perl itself\, including a potential bug in the taint checker. I would like to consult with someone to confirm this issue.

Because I don't know who is going to see this email\, I am omitting details until I hear from someone. However\, one vulnerability researcher has already alluded to the type of problem I am discussing\, so the issue is at least partially public.

It shouldn't be a big deal to discuss potential security holes on p5p\, the high volume of dense traffic tends to scare or bore any script kiddies into unsubscribing.

To err on the safe side\, send your report to the current pumpking Hugo van der Sanden \hv@​crypt\.org and he'll decide what to do with it.

The Responsible Vulnerability Disclosure Process guidelines [1] suggest that a vendor or developer should respond to an initial security vulnerability report within 7 days. I hope to hear from you within that time frame.

--

Michael G. Schwern \schwern@​pobox\.com http​://www.pobox.com/~schwern/ Perl Quality Assurance \perl\-qa@​perl\.org Kwalitee Is Job One My breasts are arousing weapons.

p5pRT commented 22 years ago

From @rgs

Steve Christey (via RT) \perlbug@​perl\.org wrote​:

However\, there is a possibility that there are security-related bugs in Perl itself\, including a potential bug in the taint checker. I would like to consult with someone to confirm this issue.

I don't include bugs in the taint checker in security bugs -- I mean\, bugs that prevent the taint checker to taint properly some data. In any case\, the taint checker is only a help for the programmer. Of course\, the security implications of any other bug\, both in standard Perl modules and in the Perl interpreter itself\, are welcome to be discussed.

p5pRT commented 22 years ago

From coley@linus.mitre.org

Hello all\,

I apologize if my vague email yesterday has caused any problems. I wanted to be certain that I was passing the report to the proper people.

In short\, Perl programs can be subjected to certain types of format string vulnerabilities [1]\, similar to C programs\, through the sprintf and printf functions. One might regard this as an implementation error and not a bug in Perl (i.e. programmers don't always use sprintf/printf correctly in Perl code\, just like they don't use them correctly in C).

However​:

1) I don't know the Perl "guts" in how it handles format strings\, so   I'm not sure whether they can be manipulated to cause buffer   overflows within Perl itself.

2) The Perl taint checker does not flag certain insecure calls early   enough to prevent some types of format string attacks. I   understand that Perl developers may decide not to modify the taint   checker to be more paranoid\, but I wanted to bring up the issue   before publishing the general risk of format strings in Perl   programs.

A more detailed writeup is below. It's a rough draft\, so I apologize for that. Corrections\, clarifications\, and Perl developer actions (if any) are appreciated. Again\, I understand that Perl developers may wish to leave the taint checker alone.

Thanks and regards\, Steve

[1] http​://online.securityfocus.com/guest/3342

*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=* Format string vulnerabilities in Perl programs *=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*

Author​: Steve Christey Date​: September 30\, 2002

Other Credits​: Jean-loup Gailly (jloup@​gailly.net) independently   discovered and reported a Perl format string problem   on September 26\, 2002 [1]


SYNOPSIS


Perl programs that provide user-controlled format strings to sprintf() and printf() may be subject to certain types of format string vulnerabilities. While the execution of arbitrary code does not appear to be feasible in the general case (as it can be with C)\, attackers may cause other behaviors that have security implications.

Many of these behaviors have analogs in C\, but since they do not result in code execution\, the implications are typically ignored in vulnerability research.

It has been observed that C programmers may use "C style" constructs when they are new to programming in Perl. Such programmers may be more likely to use printf and sprintf\, since they also appear in C.

Perl's taint checker catches the worst of these problems\, but not all of them. The behavior differs in Perl 5.004 and 5.6.1 (5.6.1 can identify additional dangerous inputs).


DETAILS


Following are some of the more dangerous/interesting specifiers\, along with their implications.

1) Using the "%n" specifier\, the attacker can modify the values of   certain variables that are provided as arguments to print/sprintf\,   possibly altering program behavior in ways that have security   implications.

  The implications of this problem depend on how the program uses the   variables.

  Consider the following pseudo-code​:

  $input = GetInputFromUser();   if (UserHasAuthenticated($user))   {   $a = 0;   }   else   {   $a = 1;   }   $str = sprintf($input\, $a);   if ($a)   {   PromptUserToAuthenticate($user);   }   else   {   DoThingThatOnlyUsersShouldDo($user);   }

  If $input is "%10s"\, then str is formatted with up to 10 spaces   of padding and $a is not modified; but if $input is "%n"\, then $a   is changed to 0\, and the attacker effectively bypasses the check   for authentication.

2) The "%s" specifier\, and others that allow field widths to be   defined\, can be used to consume a large amount of CPU\, memory\,   and/or disk\, e.g. "%99999s". (Warning​: "%999999999s" causes an   unpleasant experience on most systems.)

3) [** this needs exploration **] The "%p" and "%n" specifiers may\, in   certain situations\, be able to "leak" the values of certain   variables that was not intended by the programmer. This is because   '%p' and "%n" consume variables that are provided as arguments to   the *printf\, shifting how they are formatted.

4) Argument shifting via %p (or %n)

  [need to come up with a better term\, since shift() has meaning in Perl]

  Any format specifier can alter the intended format of structured   output. This in turn could corrupt files or enable the   exploitation of vulnerabilities in other applications that process   such output. For example\, the '%p' specifier\, which prints out a   pointer value\, could be used to generate integer values that exceed   the expected range of inputs.

  Example​:

  $index = GetUserInput();   if (($index > 32) || ($index \< 0))   {   print STDERR "Error​: Index must be between 0 and 32.";   }   ($sec\,$min\,$hour\,$mday\,$mon\,$year) = gmtime(time);   printf DATABASE\, "$index %4d/%02d/%02d %02d​:%02d​:%02d\n"\,   $year+1900\, $mon+1\, $mday;

  If $index is "1"\, then the result might be​:

  1 2002/10/01 06​:58​:42

  But if $index is "%p"\, the error condition is not detected (since   the string evaluates to 0)\, and the result would be​:

  130690 10/01/06 58​:42​:00

  Here\, not only does the 'index' value exceed the maximum of 32\, but   all the other values are wrong! This is because %p "consumes" the   $year+1900 expression\, returning a pointer to the result. All the   other arguments are then "shifted" over\, and applied to the wrong   format specifier. Thus the month value is formatted as the year\,   the seconds value is formatted as the minute\, etc.

5) Cleansing operations that remove spaces could be tricked by using   "%2s" or other format specifiers that generate spaces. Programs   may try to remove spaces when passing arguments to commands\, or   formatting data.

  Here's one example​:

  opendir(DIR\, ".");   while ($file = readdir(DIR))   {   if ($file =~ /\s/)   {   print STDERR "Warning​: '$file' has spaces\, replacing with _\n";   $file =~ s/\s/_/g;   }   if ($file =~ /^-(fiprR)+$/)   {   print STDERR "Warning​: '$file' matches switches for /bin/cp!\n";   # skip this one.   next;   }   $backup = sprintf("$file.bak"); # C programmers might do this   system("/bin/cp $file $backup"); # but this *is* just an example   }   closedir(DIR);

  If $file is set to "-R%2ssubdir"\, then the check for "dangerous   switches" would fail\, and the resulting system call would be​:

  system("/bin/cp -R subdir subdir.bak");

  [*** note​: a more feasible example could probably be created. ***]

6) Is there a way to create a format string that handles a ../ ??   Maybe not directly\, but perhaps "argument shifting" can accomplish   this?

Other Attack Scenarios


Some feasible attack scenarios involve Perl programs that generate log messages or reports​:

  - filenames containing format specifiers could alter which files are   processed

  - IP addresses whose DNS reverse lookup includes format strings   could be returned as the result of gethostbyname() [does the   taint checker spot these?]

Some discussion on format strings and the taint checker


In 5.004​:

  The taint checker apparently does not flag filenames as tainted   (e.g. as obtained from the readdir() function). Presumably\, other   types of "indirect input" may not be tainted. However\, it does   properly spot "traditional" sources of input such as stdin and   environment variables.

In 5.6.1​:

  Filenames are properly tainted\, and the taint checker properly   terminates the program. While the program is safe from   exploitation through dangerous calls\, there is still a denial of   service\, which could be a problem with critical code that is   expected to fully complete its task\, such as a log processing   program (although the programmer should take the possibility of   failure into account while running in taint mode anyway!)

  Note that the taint checker does not exit until a *printf-tainted   variable is passed to a dangerous call such as system(). So\, if   the program is not tested with specifiers such as '%n' (which   modifies an argument to *printf)\, then the taint check may not be   discovered.

  Attacks such as resource consumption and data format modification   will still work; however\, changing the taint checker to exit as   soon as the printf/sprintf is encountered could break existing   programs.

This is a factor though​: "testing" sprintf/printf with normal file names won't directly trigger the taint checker\, unless %n is actually included in the filename; so\, if the programmer tests the Perl code\, but does not include the '%n' option\, they won't necessarily find the taint error. However\, a later input with '%n' could cause the program to halt unecpectedly due to the taint error.

See taintcheck.pl for what I tried.

Note​: the taint checker doesn't complain when system() is called with arguments in the following fashion​:

  system("/bin/echo"\, $tainted_var1\, $tainted_var2);

The following example properly generates an error from the taint checker\, using input from stdin​:

  $a = \;   chomp($a);   $str = sprintf("$a.txt");   system("/bin/echo $str");

The following example also generates an error from the taint checker\, using input from a directory listing​:

  opendir(DIR\, ".");   while ($file = readdir(DIR))   {   system("/bin/echo $file");   }   closedir(DIR);

SAMPLE VULNERABLE PROGRAMS


An apparently old version of ftplogcheck\, used for processing wu-ftpd logs\, contains a line​:

  printf REPORT "$time $host $filesize $filename $name\n";

Result​: attackers can hide file activities by using format specifiers in incoming filenames that will alter the actual filename that was accessed.

perl-nocem - a script that was apparently considered for inclusion in INN 2.0 beta\, but not distributed with INN 2.3.3.

  http​://www.isc.org/ml-archives/inn-workers/2001/05/msg00177.html

The "logmsg" appears to be subject to format string issues when "use_syslog" is not active; the NNTP message ID ($msgid) looks like it could be modified with format strings such as %p\, possibly resulting in processing incorrect articles.

http​://www.lns.cornell.edu/~pvhp/perl/mac/scripts/SizeByCreator

  - seems like a user-only script

Needs investigation​:

  http​://search.cpan.org/src/JHI/perl-5.8.0/ext/Sys/Syslog/Syslog.pm

  - the syslog() function uses sprintf() on a "mask" variable;   unknown if format strings can be passed into it.

RESOLUTION


When writing Perl programs\, follow these guidelines.

1) Use constant strings for formatting.

2) Do not use Perl variables in format strings\, e.g. "$bad %10s"

3) Run your program with taint checking enabled\, which can protect   against many of the problems identified here.

DETECTION


Detection of suspicious code is slightly more difficult than it is for C code. Constant strings can contain Perl entities such as variables\, which are inserted into the string before it is passed to printf/sprintf.

  $fmt = "%10s";   printf("THIS IS A POTENTIALLY VULNERABLE $fmt FORMAT STRING\n");

************** Sample Vulnerable Programs **************

These programs demonstrate some the problems described above.

#!/bin/env perl

# when run with taint checking (-T)\, this seems to properly barf about # dependency errors (try a "clean" format string like "5s%s%s" vs. a # dirty one with a "%n" in it).

$ENV{"PATH"} = "";

# try as input​: "%s%n%s" --> modifies $b

$a = "A"; $b = "B"; $c = "C"; $x = sprintf($ARGV[0]\, $a\, $b\, $c);

print "\$a='$a'; \$b='$b'; \$c='$c'\n";

print "$x\n";

system("/bin/echo $a $b $c");

************** End Sample Vulnerable Program **************

********* Sample 2 **********

# Create a directory that contains files with these names​: # %99999s # %p # %s # abc%ndef

# This was gleaned from some real-world code\, but the print was # changed to printf.

# Change what filenames are processed via format strings in # the filenames\, such as a file named "%p%n" # # You can "erase" a filename by using '%s'\, and having this "blank" # filename could throw off the argument count to system or exec calls\, # which could alter behavior. Consider a backup command like # exec("/bin/cp"\, file1\, file2) where file1 can be "blanked" out # # Similarly\, you could "erase" portions of a filename with "%n" or # "%s". The filename ABC.TXT would be equivalent to ABC%n.%nTXT # # You can create very long filenames by using '%999s' (for example).

opendir(DIR\, "."); while ($file = readdir(DIR)) {   printf LOG "PROCESSING FILE $file\n";   # or...   # printf LOG "PROCESSING FILE " . $file . "\n"; }

2) Misuse of format string in log processing\, for which many Perl   programs have been written. Could cause larger strings than   expected to be written to files or sent to processes; code that   depends on well-formatted input from the program may be subject to   buffer overflow or other issues.

  I've seen several programs that do something like this​:

  printf "A=$a\n"

******** End Sample 2 ************

********** miscellaneous ***********

- I haven't explored all the issues

Disclosure History


Jun 10\, 2002 - Began discovery and investigation of issue; search for   potentially vulnerable programs Sep 26\, 2002 - Jean-loup Gailly (jloup@​gailly.net) posts Perl format   string problem in OpenVMS Sep 28\, 2002 - deeper investigation into format specifiers\, other   vulnerable programs Sep 30\, 2002 - more writing on security advisory; investigated whether   taint checker did "the right thing" Sep 30\, 2002 - tried to find a way to report a security vuln to Perl   developers (in case taint issue is a Perl bug\, and to   consult on possibility of buffer overflows).   Registered to site\, only to be told by a web page to   email my report to a certain address. Left out details   in the email because I had no idea who would be viewing   the report at that address. Sep 30\, 2002 - investigated taint checker issues\, %p Sep 30\, 2002 - initial response from Perl contact (within 50 minutes)   saying it was OK to post details to that address\, gave   an alternate POC just in case.

*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=* taintcheck.pl *=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*

#!/bin/env perl

# SMC 10/01/02. Test program for the taint checker.

# Before running this\, create a directory and 'touch' the following # files​: # abc%3sdef # abc%ndef # abc%pdef # abc%sdef

$ENV{"PATH"} = "/bin";

if ($ARGV[0] eq "-stdin") {   # feed tainted input from stdin through sprintf().   $a = \;   chomp($a); # $a = $ENV{"HOME"};   $str = sprintf("$a.txt");   print "STR='$str'\n";   system("/bin/echo $str"); # system("/bin/echo"\, $str);   die "No error on -stdin...\n"; } elsif ($ARGV[0] eq "-dir") {   # feed tainted input from a directory listing.   opendir(DIR\, ".");   $count = 0;   while ($file = readdir(DIR))   {   system("/bin/echo $file");   }   closedir(DIR); } elsif ($ARGV[0] eq "-dirs") {   # feed tainted input from a directory listing through sprintf().   opendir(DIR\, ".");   $count = 0;   while ($file = readdir(DIR))   {   $x = sprintf("$file.txt");   system("/bin/echo $x");   }   closedir(DIR); } elsif ($ARGV[0] eq "-dirarg") {   # feed tainted input from a directory listing through an arg   #   # This will not barf with format strings like %s\, but it *will*   # barf if it runs across a file with a %n in it.   opendir(DIR\, ".");   $count = 10;   while ($file = readdir(DIR))   {   printf "FILE=$file.txt\n"\, $count\, $a\, $b\, $c; # $c = sprintf("FILE=$file.txt\n"\, $count\, $a\, $b\, $c);   print "Fake-command​: /bin/echo count=$count a=$a b=$b c=$c\n";   system("/bin/echo count=$count a=$a b=$b c=$c");   }   closedir(DIR); } else {   print "Usage​: taintcheck.pl [-stdin|-dir|-dirs|-dirarg]\n"; }

p5pRT commented 22 years ago

From coley@linus.mitre.org

Hello\,

A week ago I notified people about the possible issues in Perl's taint checker with respect to format string issues. I have not received any responses since then.

Has the Perl development community decided that the taint checker should not be changed? If so\, then I would like to include a statement to that effect. I am delaying the release of this advisory just in case the Perl community wants to change the taint checker.

Thanks\, - Steve

p5pRT commented 21 years ago

From @ask

[christey - Tue Oct 8 16​:10​:00 2002]​:

Hello\,

A week ago I notified people about the possible issues in Perl's taint checker with respect to format string issues. I have not received any responses since then.

Has the Perl development community decided that the taint checker should not be changed? If so\, then I would like to include a statement to that effect. I am delaying the release of this advisory just in case the Perl community wants to change the taint checker.

Steve\,

Did this ever get resolved?

- ask

-- ask bjoern hansen\, http​://askbjoernhansen.com/ !try; do(); Develooper LLC\, http​://develooper.com/ $stuff->better;

p5pRT commented 21 years ago

From coley@linus.mitre.org

Hello\,

A week ago I notified people about the possible issues in Perl's taint checker with respect to format string issues. I have not received any responses since then.

Has the Perl development community decided that the taint checker should not be changed? If so\, then I would like to include a statement to that effect. I am delaying the release of this advisory just in case the Perl community wants to change the taint checker.

Did this ever get resolved?

Well\, there is a general question as to whether this should be Perl's responsibility in the first place\, or that of the application developer.

I did obtain this statement from one of the developers (unfortunately I didn't record who it was)​:

  These issues do not represent a substantial security hole in perl   itself. Future versions of perl may extend tainting checks to   format strings\, or just to certain aspects of formats (such as   %n).

- Steve

p5pRT commented 21 years ago

From @ask

[christey - Thu May 1 08​:00​:39 2003]​:

[...]

Did this ever get resolved?

Well\, there is a general question as to whether this should be Perl's responsibility in the first place\, or that of the application developer.

I did obtain this statement from one of the developers (unfortunately I didn't record who it was)​:

These issues do not represent a substantial security hole in perl
itself\.  Future versions of perl may extend tainting checks to
format strings\, or just to certain aspects of formats \(such as
%n\)\.

Hi Steve\,

I think it should be okay to discuss on p5p if you didn't already. Please feel free to file a bug with the details with the perlbug tool - the bug report will then be forwarded to perl5-porters.

Thanks!

- ask

-- ask bjoern hansen\, http​://askbjoernhansen.com/ !try; do(); Develooper LLC\, http​://develooper.com/ $stuff->better;

p5pRT commented 21 years ago

@ask - Status changed from 'new' to 'resolved'