Closed p5pRT closed 21 years ago
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
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.
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.
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 = \
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 = \
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
[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;
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
[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;
@ask - Status changed from 'new' to 'resolved'
Migrated from rt.perl.org#17698 (status was 'resolved')
Searchable as RT17698$