Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Consultation required on possible Perl security issue #5968

Closed
p5pRT opened this issue Oct 1, 2002 · 9 comments
Closed

Consultation required on possible Perl security issue #5968

p5pRT opened this issue Oct 1, 2002 · 9 comments

Comments

@p5pRT
Copy link

@p5pRT p5pRT commented Oct 1, 2002

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

Searchable as RT17698$

@p5pRT
Copy link
Author

@p5pRT p5pRT commented Oct 1, 2002

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
Copy link
Author

@p5pRT p5pRT commented Oct 1, 2002

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
Copy link
Author

@p5pRT p5pRT commented Oct 1, 2002

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
Copy link
Author

@p5pRT p5pRT commented Oct 1, 2002

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 = <STDIN>;
  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 = <STDIN>;
  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
Copy link
Author

@p5pRT p5pRT commented Oct 8, 2002

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
Copy link
Author

@p5pRT p5pRT commented Apr 30, 2003

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
Copy link
Author

@p5pRT p5pRT commented May 1, 2003

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
Copy link
Author

@p5pRT p5pRT commented Aug 10, 2003

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
Copy link
Author

@p5pRT p5pRT commented Aug 10, 2003

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

@p5pRT p5pRT closed this Aug 10, 2003
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Linked pull requests

Successfully merging a pull request may close this issue.

None yet
1 participant