rzward has asked for the wisdom of the Perl Monks concerning the following question:

Hello,

I have a perl script that makes use of eval to evaluate custom expressions passed to the script by an HTML file. It's quite a handy feature.

However, from my reading of eval, I could give a mini program to eval and it would happily run it.

Is there a way to limit the functionality of eval? For example, could I make it so eval would never cause a file to be deleted on the hard disk? Is there such a thing as "safe eval"?

If not, is there a way for me to get a list of functions referenced in a Perl string so I can disallow certain functions from being evaluated or in other words do my own restricting?

Thank you in advance for your help.

Richard

Replies are listed 'Best First'.
Re: Is there such a thing as safe eval?
by broquaint (Abbot) on May 09, 2003 at 23:11 UTC
    Is there a way to limit the functionality of eval?
    A better approach might just be to limit the functionality of perl through the magic of a Safe compartment. Using a Safe compartment you can just turn off the appropriate opcodes (as found in the Opcode module) and you can get the restricted functionality that you desire.
    HTH

    _________
    broquaint

      Thank you for the suggestion.

      I will look into Safe compartments to see how they work.

      Richard

Re: Is there such a thing as safe eval?
by gmpassos (Priest) on May 10, 2003 at 23:11 UTC
    Yes, exist! Use the module Safe.

    Here's an example of how to do that:

    use Safe ; my $PACK = new Safe ; $PACK->deny(qw( wantarray vec warn grepstart grepwhile mapstart mapwhile enteriter iter enterloop leavelo +op unstack last next redo goto readline rcatline getc read formline enterwrite leavewrite print sysread syswrite send recv eof tell seek sysseek readdir telldir seekdir rewinddir bless sprintf prtf crypt tie untie dbmopen dbmclose sselect select pipe_op sockpair getppid getpgrp setpgrp getpriority setpriority localtime gmtime rand srand atan2 sin cos exp log sqrt reset chroot syscall dump exit die warn fork lock threadsv )) ; ## I use select to turn of output: my $sel = select(NULL) ; $PACK->reval(q` ## your code that need to be safe.... `) ; ## select again the previous output: select($sel) ;
    Note that I use this to get a HASH inside a .txt file, and avoid extra functions that doesn't represent the declaration of a HASH. Than you need to check $PACK->deny and see what operators you really want to avoid.

    Graciliano M. P.
    "The creativity is the expression of the liberty".

      As others have noted in this thread, common security usage of a filtering tool is to permit only that which is known good and deeny all else, e.g.:
      use Safe ; my $PACK = new Safe ; $PACK->permit_only( # good ops here
      Bob Niederman, http://bob-n.com
Re: Is there such a thing as safe eval?
by nutshell (Beadle) on May 09, 2003 at 23:08 UTC
    I would just regex out the things I don't want evaled. e.g. $str =~ s/unlink.*;//g;

    Should work :)

    --nutshell

      With all due respect, every time you come up with something to remove, I and others can come up with something bad to put in there. For example, how would you "sanitize" the following (given the caveat that I didn't make it dangerous):

      $_ = 'sub _{local $_=shift;y/A-Z/a-z/;y/0-9//d;$_}$_=q{P1R2I3N4T "R0M +-F0R"};s/(.*)/_($1)/sexe'; eval;

      Cheers,
      Ovid

      New address of my CGI Course.
      Silence is Evil (feel free to copy and distribute widely - note copyright text)

      Generally speaking, the opposite approach is the way to go for most security situations. Disallow everything and only open what you want.

      So if you have a handful of commands you're willing to eval, you could regex verify them. But trying to build a stop-list of things not to eval is fraught with terror, as Ovid demonstrates above.

      Thank you for your suggestion.

      To do a good job using regex I think I would need to know the difference between unlink the function and $unlink the variable (it might happen!) So I would basically be building a Perl parser for the string and complaining if the parser encountered any in my list of illegal functions.

      I don't think this is very difficult but is there another way of doing this that is more reliable?

      Richard