develooper Front page | perl.perl5.porters | Postings from November 2005

My reply to the Perl flaw article

Thread Next
From:
Andy Lester
Date:
November 30, 2005 10:19
Subject:
My reply to the Perl flaw article
Message ID:
20051130181903.GH21660@petdance.com
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 => andy@petdance.com => www.petdance.com => AIM:petdance

Thread Next


nntp.perl.org: Perl Programming lists via nntp and http.
Comments to Ask Bjørn Hansen at ask@perl.org | Group listing | About