For Programmers: Free Programming Magazines  


Home > Archive > PERL Modules > May 2004 > [Safe.pm] Problem with nested reval() calls









You are viewing an archived Text-only version of the thread. To view this thread in it's original format and/or if you want to reply to this thread please [click here]

 

Author [Safe.pm] Problem with nested reval() calls
Paul Kulchenko

2004-05-04, 1:00 pm

Hi,

I've been trying to evaluate strings that use tied variables in a Safe
compartment and having a problem with running nested reval calls. The
example below.

This script generates "Global symbol "%a" requires explicit package
name at ..." error even though it's clear that %a symbol is seen when
reval is called first time. (surely the script runs just fine with
simple eval().)

If I remove the second call in line 26, then the script runs just fine
and prints '4'.
If I remove 'strict' (second parameter in reval()) in line 16, then
script runs with no error, but prints only '4' instead of '46' (as it
doesn't see %a var).

Any explanation or workaround to run this script are greatly
appreciated. Thanks.

Paul.

P.S. I carefully looked at other posts on this topic, like old
Graham's post [1] about Safe being fundamentally broken by not
allowing proper method calls, at Safe::Hole that is written to fix
this problem [2], and Ilya's hint [3] about reval() messing with the
symbol table.

[1] http://groups.google.com/groups?hl=...40ti.com&rnum=8
[2] http://groups.google.com/groups?q=s...cn.ad.jp&rnum=9
[3] http://groups.google.com/groups?q=s...eley.edu&rnum=6
use strict;

package B;

use Safe;

use vars '%a';
tie %a => 'A';
my $s = new Safe 'SR';
$s->permit(qw(entereval :browse));
$s->share('%a');

sub build {
my $self = shift;
my $eval = shift;
my $output = $s->reval("qq\0$eval\0", 1); die if $@; # 16
# my $output = eval("qq\0$eval\0"); die if $@;
$output;
}

package A;
require Tie::Hash; use vars '@ISA'; @ISA = qw(Tie::Hash);

sub TIEHASH { my $self = shift; bless { @_ } => $self }
sub FETCH {
$_[1] . ($_[1] == 4 ? B::build(B => '$a{3+3}') : ''); # 26
}

package main;

print B->build('$a{2+2}');
Brian McCauley

2004-05-12, 7:20 pm

paulclinger@yahoo.com (Paul Kulchenko) writes:

> To answer my own question.
>
>
> This needs to be changed to:
>
> my $output = $s->reval("sub{qq\0$eval\0}", 1); die if $@; # 16
> $output->();


> Is there anything I'm missing?


Safety.

If the code is executed outside the safe compartment it has access to
the true symbol table and thus could call any subroutine that's in
memory with arbitrary arguments.

--
\\ ( )
. _\\__[oo
.__/ \\ /\@
. l___\\
# ll l\\
###LL LL\\
Ilya Zakharevich

2004-05-12, 7:20 pm

[A complimentary Cc of this posting was sent to
Brian McCauley
<nobull@mail.com>], who wrote in article <u97jvpkdy2.fsf@wcl-l.bham.ac.uk>:
>
> Safety.
>
> If the code is executed outside the safe compartment it has access to
> the true symbol table and thus could call any subroutine that's in
> memory with arbitrary arguments.


???

Safe gives absolutely no protection for access to "the true symbol
table". A 2-line sample using absolutely straightforward Perl code
(only stuff explained in the first couple of hours of Perl course),
and you run with "the true symbol table" visible, and can "any
subroutine that's in memory with arbitrary arguments".

When I reported this to p5p a year ago, there was no reaction; I
assume this means that this matter is well-known, and was new for me
only because I do not use it (knowing no usage for Safe whatsoever).

Hope this helps,
Ilya
Paul Kulchenko

2004-05-12, 7:20 pm

Brian McCauley <nobull@mail.com> wrote in message news:<u97jvpkdy2.fsf@wcl-l.bham.ac.uk>...

> If the code is executed outside the safe compartment it has access to
> the true symbol table and thus could call any subroutine that's in
> memory with arbitrary arguments.


Unlikely. Only _compiled_ code is executed outside the compartment and
it _only_ has access to what was accessible when it was being
compiled. It won't compile unless you _share_ that variable/sub with
that compartment (which I don't) or use eval (which I don't allow). Am
I still missing something?

Could someone perhaps show the code that does what I don't want it to
do?

Paul.
Brian McCauley

2004-05-12, 7:20 pm

paulclinger@yahoo.com (Paul Kulchenko) writes:

> Brian McCauley <nobull@mail.com> wrote in message news:<u97jvpkdy2.fsf@wcl-l.bham.ac.uk>...
>
>
> Unlikely. Only _compiled_ code is executed outside the compartment and
> it _only_ has access to what was accessible when it was being
> compiled. It won't compile unless you _share_ that variable/sub with
> that compartment (which I don't) or use eval (which I don't allow). Am
> I still missing something?


Yes, symbolic references.

Note: explicit convertion of a symbolic code reference to a hard code
reference is exempt from strict. This is because the purpose of
strict is to prevent you _accidently_ making perl think you want
symrefs. Explicit convertion is not likely to be an accident!

> Could someone perhaps show the code that does what I don't want it to
> do?


sub forbidden { print "forbidden\n"; }

my $eval = '@{my $x="main::forbidden"; $x=\&$x; $x->(); []}';

my $output = $s->reval("sub{qq\0$eval\0}", 1);
die $@ if $@;
$output->(); # calls &main::forbidden

--
\\ ( )
. _\\__[oo
.__/ \\ /\@
. l___\\
# ll l\\
###LL LL\\
Brian McCauley

2004-05-12, 7:20 pm

Ilya Zakharevich <nospam-abuse@ilyaz.org> writes:

> <nobull@mail.com> wrote in article <u97jvpkdy2.fsf@wcl-l.bham.ac.uk>:


[color=darkred]
> Safe gives absolutely no protection for access to "the true symbol
> table". A 2-line sample using absolutely straightforward Perl code
> (only stuff explained in the first couple of hours of Perl course),
> and you run with "the true symbol table" visible,


> When I reported this to p5p a year ago, there was no reaction; I
> assume this means that this matter is well-known,


Or perhaps it just didn't propagate well - I've just done a Google
groups search on "Ilya Zakharevich safe group:perl.perl5.porters" and
the nearest thing I could find was a post where you assert:

> Basically, with
>
> sub foo {
> my $res = Safe->new->reval(shift);
> die $@ if $@;
> }
>
> I can run arbitrary code with :default permissions with %main:: fully
> visible.


So you _assert_ that there is something you can pass to foo() that will
be able to manipulate the true %main:: but you don't show us what it is.

Can since you say it's only "2-line sample using absolutely
straightforward Perl code (only stuff explained in the first couple of
hours of Perl course)" could I ask that you generate a minimal but
complete script illustrating how you would do this. (Without using
bless, I know there are numerous exploits if you allow the bless
opcode).

--
\\ ( )
. _\\__[oo
.__/ \\ /\@
. l___\\
# ll l\\
###LL LL\\
Paul Kulchenko

2004-05-12, 7:20 pm

Brian McCauley <nobull@mail.com> wrote in message news:<u9r7twijab.fsf@wcl-l.bham.ac.uk>...

> sub forbidden { print "forbidden\n"; }
>
> my $eval = '@{my $x="main::forbidden"; $x=\&$x; $x->(); []}';
>
> my $output = $s->reval("sub{qq\0$eval\0}", 1);
> die $@ if $@;
> $output->(); # calls &main::forbidden


As far as I understand, that works only with sub dereference and
"$s->deny('rv2cv');" can protect against that (plus "use strict;"). Is
there anything else (bad) you can come up with? ;)

Paul

P.S. "perl -MO=Terse -e '<bad command>'" might be useful
Ilya Zakharevich

2004-05-12, 7:20 pm

[A complimentary Cc of this posting was sent to
Brian McCauley
<nobull@mail.com>], who wrote in article <u9oep0ihg0.fsf@wcl-l.bham.ac.uk>:
>
> So you _assert_ that there is something you can pass to foo() that will
> be able to manipulate the true %main:: but you don't show us what it is.


Correct. And this is exactly the typical situation Safe is used in.

> Can since you say it's only "2-line sample using absolutely
> straightforward Perl code (only stuff explained in the first couple of
> hours of Perl course)" could I ask that you generate a minimal but
> complete script illustrating how you would do this. (Without using
> bless, I know there are numerous exploits if you allow the bless
> opcode).


Of course I have such a script. It uses bless() indeed, but since
bless() is allowed by the default mask, I see no reason why not use
it.

Hope this helps,
Ilya
Paul Kulchenko

2004-05-12, 7:20 pm

Ilya Zakharevich <nospam-abuse@ilyaz.org> wrote in message news:<c7jgje$var$1@agate.berkeley.edu>...

> Of course I have such a script. It uses bless() indeed, but since
> bless() is allowed by the default mask, I see no reason why not use
> it.


Does this mean that it is "safe" to use this:

$s->permit_only(qw(:base_core :base_mem gv refgen));

or that at least there are no known exploits for this set of opcodes?

Paul.
Brian McCauley

2004-05-12, 7:21 pm

paulclinger@yahoo.com (Paul Kulchenko) writes:

> Brian McCauley <nobull@mail.com> wrote in message news:<u9r7twijab.fsf@wcl-l.bham.ac.uk>...
>
>
> As far as I understand, that works only with sub dereference and
> "$s->deny('rv2cv');" can protect against that (plus "use strict;"). Is
> there anything else (bad) you can come up with? ;)


As I've already pointed out in this tread "use strict" still allows
some uses of symref. rv2cv is one I knew about but there could be
others.

More importantly you can do a class method call.

'main'->forbidden() but this doesn't give total control over the
argument list - the first argument has to be a valid Perl identifier:

@foo::ISA = 'main';
foo->fobidden(); # Calls main::fobidden('foo')

Disabling method calls is probably too restrictive for most uses of Safe.

--
\\ ( )
. _\\__[oo
.__/ \\ /\@
. l___\\
# ll l\\
###LL LL\\
Brian McCauley

2004-05-12, 7:21 pm

Ilya Zakharevich <nospam-abuse@ilyaz.org> writes:

> [A complimentary Cc of this posting was sent to
> Brian McCauley
> <nobull@mail.com>], who wrote in article <u9oep0ihg0.fsf@wcl-l.bham.ac.uk>:
>
> Correct. And this is exactly the typical situation Safe is used in.


Yes, I know that in all security matters you don't know in advance
what the exploit will be. However if you were always to believe all
unsupported assertions that a weakness exists you'd never realease
anything.

>
> Of course I have such a script. It uses bless() indeed, but since
> bless() is allowed by the default mask, I see no reason why not use
> it.


I'm curious - does your exploit require the code to guess the name of
the false root package? (All those I know do). If so then a
cryptographically stong random name generator would be a viable
defense.

> Hope this helps,


That's a pretty vain hope.


--
\\ ( )
. _\\__[oo
.__/ \\ /\@
. l___\\
# ll l\\
###LL LL\\
Brian McCauley

2004-05-12, 7:21 pm

Ilya Zakharevich <nospam-abuse@ilyaz.org> writes:

> Brian McCauley <nobull@mail.com> wrote:
>
>
> It uses bless()


I'd be interested to see the structure[2] of this Perl course where
bless is explained[1] in the first couple of hours. Assuming the
course is logically structured then this means that in two hours we've
managed to get the students to the point where they are ready to start
looking under-the-hood of Perl objects.

[1] Not just mentioned, explained.

[2] Got a URL?

--
\\ ( )
. _\\__[oo
.__/ \\ /\@
. l___\\
# ll l\\
###LL LL\\
Paul Kulchenko

2004-05-12, 7:21 pm

Brian McCauley <nobull@mail.com> wrote in message news:<u9d65clc7x.fsf@wcl-l.bham.ac.uk>...

> More importantly you can do a class method call.
>
> 'main'->forbidden() but this doesn't give total control over the
> argument list - the first argument has to be a valid Perl identifier:
>
> @foo::ISA = 'main';
> foo->fobidden(); # Calls main::fobidden('foo')


Good point. 'method' (which includes 'method_named') should take care
of "foo->forbidden" and "$f = 'forbidden'; foo->$f()" calls.

Anything else? I think we're getting close to the competition that
Ilya had in mind ;).

> Disabling method calls is probably too restrictive for most uses of Safe.


agreed. It works for me though (for now; I haven't implemented yet all
the functionality I need). Thanks!

Paul.
Ilya Zakharevich

2004-05-12, 7:21 pm

[A complimentary Cc of this posting was sent to
Brian McCauley
<nobull@mail.com>], who wrote in article <u98yg0lbce.fsf@wcl-l.bham.ac.uk>:

Actually, bless() is not required. There should be many other ways to
trigger the same semantic...
[color=darkred]
> I'm curious - does your exploit require the code to guess the name of
> the false root package? (All those I know do). If so then a
> cryptographically stong random name generator would be a viable
> defense.


No, it does not require anything. Absolutely plain absolutely
standard Perl code, one you see all the time.

Given that "security by obscurity" *has* its benefits, I won't post
the code in publicly readable places. Or if there is a list of places
where I can see the known exploits, I could check whether this one is
well-known...

Hope this helps,
Ilya
Ilya Zakharevich

2004-05-12, 7:21 pm

[A complimentary Cc of this posting was sent to
Brian McCauley
<nobull@mail.com>], who wrote in article <u93c68kzx0.fsf@wcl-l.bham.ac.uk>:
> I'd be interested to see the structure[2] of this Perl course where
> bless is explained[1] in the first couple of hours.


;-) Point taken.

Thanks,
Ilya
Paul Kulchenko

2004-05-12, 7:21 pm

Ilya Zakharevich <nospam-abuse@ilyaz.org> wrote in message news:<c7p2hk$2nk4$1@agate.berkeley.edu>...

> Actually, bless() is not required. There should be many other ways to
> trigger the same semantic...
>
>
> No, it does not require anything. Absolutely plain absolutely
> standard Perl code, one you see all the time.
>
> Given that "security by obscurity" *has* its benefits, I won't post
> the code in publicly readable places. Or if there is a list of places
> where I can see the known exploits, I could check whether this one is
> well-known...


This doesn't help at all. Either you need to provide a solution (at
least a set of opcodes to deny) or you need to share the exploit, so
the solution can be found. Unless you're saying that there is NO
protection from that exploit and that Safe is fundamentally unsafe.

Paul.
Ilya Zakharevich

2004-05-12, 7:21 pm

[A complimentary Cc of this posting was sent to
Paul Kulchenko
<paulclinger@yahoo.com>], who wrote in article <88fe3111.0405110739.71be74a@posting.google.com>:
> Ilya Zakharevich <nospam-abuse@ilyaz.org> wrote in message news:<c7p2hk$2nk4$1@agate.berkeley.edu>...
> This doesn't help at all. Either you need to provide a solution (at
> least a set of opcodes to deny) or you need to share the exploit, so
> the solution can be found. Unless you're saying that there is NO
> protection from that exploit and that Safe is fundamentally unsafe.


??? After how many, 7(?) year of existance of Safe you still have any
doubt about Save being unsafe?

Puzzled,
Ilya
Sponsored Links







Also available: Server administration forum archive | Web Design forum archive | Software forum archive | Hardware reviews archive

Copyright 2008 codecomments.com