Beefy Boxes and Bandwidth Generously Provided by pair Networks
Your skill will accomplish
what the force of many cannot

Perl sandbox

by gildir (Pilgrim)
on Nov 06, 2001 at 19:05 UTC ( #123587=perlquestion: print w/replies, xml ) Need Help??

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

Fellow monks,

Recently I have made some experiments with Safe module, and that induced one idea in my head. I will explain it on an example.

Imagine that you are writing public CGI service or some templating system or whatever that includes perl code snippets. For speed optimizations you want to compile that public perl code once and run it many times over. Simple task so far, just use my $sub = eval "sub { $code }";. But, what if user includes open(P,"/etc/passwd"); print(<P>); in his code?

One possible solution is still simple, use a Safe module to restrict open opcode (as shown in Safe module security and emebeded perl). But I want an open function to be accessible to user, for example to enable user include his own files that are in his home directory, but nothing else.

And now the question:
Is there some way how to 'trap' some opcodes in perl, inspect arguments and then resume execution if everything is OK? I seek funcionality very similar to Java sandbox. Can this be done in perl?

N.B. chroot is no solution. It will work for open, but not for other calls. For example it won't affect opening a socket to source server only in applet-like scenario.

Replies are listed 'Best First'.
Re: Perl sandbox
by Fletch (Bishop) on Nov 06, 2001 at 20:07 UTC

    You might could use B::Generate to muck about with the OP tree, but you'd be getting into very deep wizardry (not that you're in the kiddie pool with Safe to begin with :).

    Simpler might be to write a replacement open that disallows absolute paths and paths with `..' in them and only allow that sub to be called from the compartment.

Re: Perl sandbox
by jepri (Parson) on Nov 06, 2001 at 21:41 UTC
    I did some 'research' into this about a year ago with the same goal. The conclusion I came to was that for mere mortals like me, there was no way to *really* secure perl without turning it into an language as braindead as javascript.

    In my case I wanted a database backend that people could run small routines against (to make some kind of extendable web community). I thought I could use the Tie::modules but it turns out using any kind of module opens the flood gates.

    A suprising number of reasonable commands rely on the same opcodes that 'dangerous' commands rely on. I don't know the design of Perl5 but I've been checking out Perl6 and the Parrot interpretor looks like it's going to have the same problems. While security is best done at the OS level Perl seems to go out of it's way to be hard to secure.

    An easier solution is to use the Inline:: series of modules to allow users to program in Basic, Java, C, CPP, Befunge, BrainF**k or whatever. These language lack the power of perl, but they also lack the security dangers.

    I didn't believe in evil until I dated it.

Re: Perl sandbox
by alien_life_form (Pilgrim) on Nov 06, 2001 at 21:50 UTC

    I am not very familiar with Safe, so I do not know if this would work:

    1. Override open, somewhere.
    2. your newfanlged open runs the arguments checks
    3. it calls CORE::open if satisfied
    This can be repeated ad libitum (though overriding some of the operators will probably require some heavy prototyping, if they are to look and feel exactly the same as the originals...).


    You can't have everything: where would you put it?
Re: Perl sandbox
by cLive ;-) (Prior) on Nov 06, 2001 at 22:22 UTC
    Is it possible to roll your own "safeopen" function? I'm not sure, but wouldn't an OO module incorporating the FileHandle module do the trick? s/earch/and replace/ all filehandle statements to point to the OO code instead.

    Then you can parse all paths/files and maybe stat them to find out who owns them before allowing/disallowing access.


    cLive ;-)

Re: Perl sandbox
by mr_mischief (Monsignor) on Nov 08, 2001 at 00:58 UTC
    Short of parsing Perl in your solution, there's really no good way to do this. Since nothing can really parse Perl but perl, you'd have to look into the B family of modules for the best way to do this.

    You could try reading all the user-supplied code in as data items which are tainted, and run some really massive untaint checks against them -- preferably something in XS that doesn't mark them as untainted until it has run several checks against each value. Then, the process just dies if you try to eval a tainted piece of code. Any solution such as this would be a hairy kludge, but it could be made to work in theory. I wouldn't volunteer to maintain such a mess in any case. Writing and maintaining the taint checks would be referred to by a choice four-letter word.

    It's good to remember that Java was designed to be an applet language from the start. Perl was designed to get real work done from the start. The two design goals are difficult to have at once, especially if they are not both primary concerns from the beginning. Even Java advocates will tell you that it's a much more powerful language when run in an unrestricted application mode than as an applet in a sandbox.

    If you want just a subset of Perl but with strict controls on things, you could write a parser for that subset. It could be far easier than parsing all of Perl, depending upon how much of it you want to include.

    You could hack the core to make the checks for you. This would likely make Perl a slow memory hog instead of a fast memory hog like it is now. I can deal with memory issues for the most part. Memory is cheap. Time is expensive. This solution would also be a real pain. It would likely force a split between sandboxed perl and the perl core unless there's a way to keep the checks from slowing the opcodes down when they are not in use. Splits are bad. Slowing down the core for a feature not currently in use is bad, too.

    If all the functions you feel are unsafe are mutable, then you could override them all to make the necessary checks before performing any actions. This, though, would practically be laguage design work in its own right. If you go through this much trouble, please make it a module. It could be useful to others once it's done.


Log In?

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://123587]
Approved by root
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others browsing the Monastery: (4)
As of 2022-08-18 16:47 GMT
Find Nodes?
    Voting Booth?

    No recent polls found