develooper Front page | perl.perl5.porters | Postings from July 2012

NWCLARK TPF grant report #43

From:
Nicholas Clark
Date:
July 25, 2012 05:54
Subject:
NWCLARK TPF grant report #43
Message ID:
20120725125353.GI9834@plum.flirble.org
[Hours]		[Activity]
2012/06/25	Monday
 1.00		smoke-me/require
 2.00		reading/responding to list mail
=====
 3.00

2012/06/26	Tuesday
 4.25		reading/responding to list mail
=====
 4.25

2012/06/27	Wednesday
 0.50		ID 20020306.011 (RT #8800)
 5.50		smoke-me/require
 1.00		pp_require
 3.00		reading/responding to list mail
=====
10.00

2012/06/28	Thursday
 0.25		RT #16249
 1.50		smoke-me/require
 3.75		pp_require
=====
 5.50

2012/06/29	Friday
 3.25		smoke-me/require
 0.25		named arguments in prototypes
 3.50		pp_require
 0.50		reading/responding to list mail
=====
 7.50

2012/06/30	Saturday
 0.75		bisect.pl (Debian multiarch)
 0.50		named arguments in prototypes
=====
 1.25

2012/07/01	Sunday
 2.00		smoke-me/require
=====
 2.00

Which I calculate is 33.50 hours

Two thirds of that was investigating and iterating fixes for the various
bugs now fixed on the smoke-me/require.

There are two partly related problems. Both affect code which takes
untrusted user data and passes it to routines that load code (a risky thing
to do at the best of times), but doesn't perform sufficiently strong
validation. The called routines could detect that the passed in string is
crazy, but don't, and instead proceed to treat it in surprising ways.

Note, this only affects programs that

1) are "brave" enough to load *code* from disk using package names provided
   by user data
2) don't validate that user data thoroughly

(ie a generally bad idea, and a definitely bad implementation)


The first is accessible from Perl-space:

    $ cat /tmp/foo.pm
    print STDERR __FILE__ . " was not the file you expected to get loaded?\n";
    $ ~/Sandpit/5000/bin/perl -e 'require ::tmp::foo;' 
    /tmp/foo.pm was not the file you expected to get loaded?
    $ echo $?
    0

and is present for every version of Perl 5 ever. (Perl 4 is safe)

Of course, to be bitten by that you have to pass *user data* to a *string
eval* containing require, which is already a risky thing to be doing, 
and this *only* increases the attack space from "all readable files in @INC
ending .pm" to "all readable files on disk ending .pm"

Plus if you're already passing user data to string eval, it's usually much
easier to do direct nasties - eg strings such as
"less; system 'sudo rm -rf /'"

So this probably doesn't expose any holes in programs that weren't already
completely unseaworthy.

It's also rather hard to search CPAN to work out if there's any code which
is unwise enough to be at risk from this.


The second is accessible only to C and XS code that call the APIs
function Perl_load_module() or Perl_vload_module(). These are documented
as taking a module name (ie "Foo::Bar"), not a file name (ie not
"Foo/Bar.pm"). However, they don't validate what they are passed, so module
names such as "Foo::..::..::..::Bar" are subject to the standard s!::!/!g
transformation, which obviously can be used to produce "interesting"
filenames.

Perl_load_module() has been available since 5.6.0.

Note, again this only affects programs that

1) are "brave" enough to load *code* from disk using package names provided
   by user data
2) don't validate that user data thoroughly

(ie a generally bad idea, and a definitely bad implementation)

and again this *only* increases the attack space from all readable files in
@INC to all readable files on disk.

Nothing on CPAN uses Perl_vload_module(), and (as best I can tell from
searching) only two modules on CPAN use Perl_load_module() on values that
aren't constants or tightly controlled at the C level. The authors of both
modules are aware, and have checked their code.

Nicholas Clark



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