Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

My reply to the Perl flaw article

1 view
Skip to first unread message

Andy Lester

unread,
Nov 30, 2005, 1:19:03 PM11/30/05
to Perl 5 Porters
Please see http://petdance.com/random/reply.html for the HTML version of
what I plan to post this afternoon. I'm already in touch with the
author at CNET who got the headline changed from "Perl flaw" to "Perl
app flaw".

The article "Danger level rises for Perl app flaws" (http://news.com.com/2100-1002_3-5975954.html) points out an important security hole in the Webmin web administration package. Unfortunately, the article emphasizes that Webmin is written in Perl, as if Perl is the cause of the problem. The problem is not unique to Perl, and Perl actually has a distinctive built-in feature that helps programmers fight these sort of coding errors.

The problem of using format strings from untrusted sources goes back to C, but doesn't go away with newer dynamic languages such as Perl, Python, PHP and Ruby. A printf format string is source code in a mini-language of its own, and should not be brought in from outside sources, regardless of the language being used.

In C, this can be as simple as:

untrusted_format = "%1000000d";
sprintf( buffer, untrusted_format, 1 );

The buffer is overrun (unless it is at least 1,000,000 bytes long), potentially smashing executable code and allowing an attacker to inject malicious code bytes to be executed with the permissions of the process.

In Perl, while the same sort of bad coding is possible:

$untrusted_format = "%1000000d";
$buffer = sprintf( $untrusted_format, 1 );

the effects are much less. Perl would allocate a 1,000,000 byte string, which could be a resource drain, or may cause the interpreter to run out of memory, but should not allow executable memory to be modified.

Please note that miniserv.pl uses Perl's Sys::Syslog module, and that Sys::Syslog uses uses Perl's internal sprintf function, not the C library. While there is indeed a possibility that an attacker could mount a denial of service attack, he should not be able modify executable code.

The answer to these problems in all cases, especially in the case of Webmin's miniserv.pl program, is to not pass untrusted data into printf format strings. This is important especially in light of the recently discovered printf integer overrun mentioned at http://www.dyadsecurity.com/adv/perl.adv.

Keeping track of which data comes from where can be daunting for the programmer, but Perl has features that make this easier. One of Perl's great unheralded features is variable tainting. Perl considers all data from sources outside of the running program as "tainted." Consider this extremely simplified, extremely dangerous case:

$dir = CGI->param( 'dir' );
$cmd = "ls $dir";
@files = `$cmd`; # Execute shell command and return results
# Now display @files to the user

The intent is that the programmer wants to get a directory name from a web form, and get a list of files in that directory. If an attacker passes the value "; rm -fr /", the actual command executed will be "ls ; rm -fr /", which is two commands: One to list the current directory, and one to delete all the files in the filesystem.

With Perl's taint checking enabled, the programmer can't accidentally make this happen. Since $dir comes from an external, untrusted source, it is marked as tainted. "External untrusted source" includes all environment data, data from sockets, and all file input (see the perlsec manual page, at http://perldoc.perl.org/perlsec.html for a complete list). When the Perl interpreter sees that it's asked to execute a command from a tainted string, it refuses:

Insecure dependency in `` while running with -T switch at ./programname.pl line XX.

Taint checking is also supported in the de facto standard database module DBI. With taint checking enabled, tainted data cannot be used as SQL statements, as parameters for data to be saved to a database. This taint checking can help ensure that the programmer doesn't inadvertantly open up code to SQL injection attacks. Further, data from a database is marked as tainted upon retrieval.

Of course, programmers need to be able to untaint data from external sources to make it safe to use, and Perl's powerful, integrated regular expression handling makes this possible. Programmers specify that data must match a certain pattern, and extract only that data that passes this safety check. For common untainting tasks, the CGI::Untaint family of modules make it a simple function call.

While taint checking would not have helped with this Webmin bug, the Perl core developers are currently considering changes to Perl's printf family of functions to fail if the format string is tainted. Perl's developers are also working to squash the integer overflow format bug.

Perl's taint checking is all but unique in programming languages. PHP and Java do not support the concept, and Ruby's support has just started.

About the Perl Foundation: The Perl Foundation is dedicated to the advancement of the Perl programming language through open discussion, collaboration, design, and code. The Perl Foundation is a non-profit, 501(c)(3) organization based in Holland, Michigan. For followup, please email pr at perlfoundation.org.


--
Andy Lester => an...@petdance.com => www.petdance.com => AIM:petdance

Gisle Aas

unread,
Nov 30, 2005, 1:45:24 PM11/30/05
to Andy Lester, Perl 5 Porters
Andy Lester <an...@petdance.com> writes:

> $untrusted_format = "%1000000d";
> $buffer = sprintf( $untrusted_format, 1 );
>
> the effects are much less. Perl would allocate a 1,000,000 byte
> string, which could be a resource drain, or may cause the
> interpreter to run out of memory, but should not allow executable
> memory to be modified.

I think you should drop this part as current perls do have buffer
overflow issues with widths close to 2**32, even if 1000000 should be
fine.

--Gisle

Jan Dubois

unread,
Nov 30, 2005, 2:16:03 PM11/30/05
to Andy Lester, Perl 5 Porters
On Wed, 30 Nov 2005, Andy Lester wrote:
> The problem of using format strings from untrusted sources goes back
> to C, but doesn't go away with newer dynamic languages such as Perl,
> Python, PHP and Ruby. A printf format string is source code in a mini-
> language of its own, and should not be brought in from outside
> sources, regardless of the language being used.

I would not claim other languages have the same problem unless you
first verify that they do. For example Python does seem to have a
check for this situation:

| ActivePython 2.3.2 Build 232 (ActiveState Corp.) based on
| Python 2.3.2 (#49, Nov 13 2003, 10:34:54) [MSC v.1200 32 bit (Intel)] on win32
| Type "help", "copyright", "credits" or "license" for more information.
| >>> print "%4294967295d" % 1
| Traceback (most recent call last):
| File "<stdin>", line 1, in ?
| ValueError: width too big
| >>>

Let's just deal with our own problems without dragging others into it.
A printf format string should not be able to generate an access violation.
If it does, it is a bug.

I do agree with the rest of the article that the application developer
is most to blame for not properly checking their input data.

Cheers,
-Jan


Joshua Juran

unread,
Nov 30, 2005, 2:30:35 PM11/30/05
to Perl Porters
On Nov 30, 2005, at 1:19 PM, Andy Lester wrote:

> Please see http://petdance.com/random/reply.html for the HTML version
> of
> what I plan to post this afternoon. I'm already in touch with the
> author at CNET who got the headline changed from "Perl flaw" to "Perl
> app flaw".

I'd imagine "Web app flaw" would be even more accurate, since the whole
point is that you're protecting against untrusted remote users, not
which language you failed to do it in. But you've addressed that
below.

My pedantry follows:

> The article "Danger level rises for Perl app flaws"
> (http://news.com.com/2100-1002_3-5975954.html) points out an important
> security hole in the Webmin web administration package. Unfortunately,
> the article emphasizes that Webmin is written in Perl, as if Perl is
> the cause of the problem. The problem is not unique to Perl, and Perl
> actually has a distinctive built-in feature that helps programmers
> fight these sort of coding errors.

Pick one of:
"this sort of coding error"
"these sorts of coding errors"

> The problem of using format strings from untrusted sources goes back
> to C, but doesn't go away with newer dynamic languages such as Perl,
> Python, PHP and Ruby. A printf format string is source code in a
> mini-language of its own, and should not be brought in from outside
> sources, regardless of the language being used.
>
> In C, this can be as simple as:
>
> untrusted_format = "%1000000d";
> sprintf( buffer, untrusted_format, 1 );
>
> The buffer is overrun (unless it is at least 1,000,000 bytes long),
> potentially smashing executable code and allowing an attacker to
> inject malicious code bytes to be executed with the permissions of the
> process.
>
> In Perl, while the same sort of bad coding is possible:
>
> $untrusted_format = "%1000000d";
> $buffer = sprintf( $untrusted_format, 1 );
>
> the effects are much less. Perl would allocate a 1,000,000 byte
> string, which could be a resource drain, or may cause the interpreter
> to run out of memory, but should not allow executable memory to be
> modified.
>
> Please note that miniserv.pl uses Perl's Sys::Syslog module, and that
> Sys::Syslog uses uses Perl's internal sprintf function, not the C
> library. While there is indeed a possibility that an attacker could
> mount a denial of service attack, he should not be able modify
> executable code.

"Sys::Syslog uses uses Perl's internal sprintf" has more "uses" than
expected...

Adjective-to-noun binding has higher precedence than adjective-phrase
concatenation, so use hyphens the way you would parentheses: "mount a
denial-of-service attack".

Try "should not be able TO modify".

> The answer to these problems in all cases, especially in the case of
> Webmin's miniserv.pl program, is to not pass untrusted data into
> printf format strings. This is important especially in light of the
> recently discovered printf integer overrun mentioned at
> http://www.dyadsecurity.com/adv/perl.adv.

Following a bare URL with punctuation is asking for trouble. I'd write
<http://www.dyadsecurity.com/adv/perl.adv>. But I suppose that's just
an artifact of copying the Web page into an email, and only an issue in
that case.

"the CGI::Untaint family of modules make it...": Should be "makes it",
since "family" is the subject.

> While taint checking would not have helped with this Webmin bug, the
> Perl core developers are currently considering changes to Perl's
> printf family of functions to fail if the format string is tainted.
> Perl's developers are also working to squash the integer overflow
> format bug.
>
> Perl's taint checking is all but unique in programming languages. PHP
> and Java do not support the concept, and Ruby's support has just
> started.
>
> About the Perl Foundation: The Perl Foundation is dedicated to the
> advancement of the Perl programming language through open discussion,
> collaboration, design, and code. The Perl Foundation is a non-profit,
> 501(c)(3) organization based in Holland, Michigan. For followup,
> please email pr at perlfoundation.org.

Josh

0 new messages