22

I want to execute a php-script from php that will use different constants and different versions of classes that are already defined.

Is there a sandbox php_module where i could just:

sandbox('script.php'); // run in a new php environment

instead of

include('script.php'); // run in the same environment

Or is proc_open() the only option?

PS: The script isn't accessible through the web, so fopen('http://host/script.php') is not an option.

Bob Fanger
  • 28,949
  • 7
  • 62
  • 78

7 Answers7

10

There is runkit, but you may find it simpler to just call the script over the command line (Use shell_exec), if you don't need any interaction between the master and child processes.

troelskn
  • 115,121
  • 27
  • 131
  • 155
  • 2
    About runkit; it does not seem to sandbox well by description, or I maybe should say easy. You can forbid functions, but I would rather like to forbid ALL but those in a provided list. If an user needs a function I can evaluate its safety by hand upon request. It seems like the only way is to write a custom made interpreter. If speed is an issue you can make it convert its AST into PHP or an other language, this is actually what I'm gonna do now as I could not find a ready solution. Cheers! Ps. Yes, I saw that this Q is old. Ds. – Frank Jun 14 '10 at 15:38
  • Well .. Good luck finding something that can parse PHP into an AST ;) I concur with your point though. – troelskn Jun 14 '10 at 17:27
  • FYI runkit seems to be abandoned and you'll probably want to compile either the CVS version or one of the patched versions (http://github.com/tricky/runkit) if you want to run it on a modern version of PHP – Eli Jul 21 '10 at 14:21
6

The is a class on GitHub that may help, early stages but looks promising.

https://github.com/fregster/PHPSandbox

Paul
  • 71
  • 1
  • 1
2

There is Runkit_Sandbox - you might get it to work, it's a PHP extension. I'd say the way to go.

But you might need to create a "sandbox" your own, e.g. by resetting the global variable state of the superglobals you use.

class SandboxState
{
    private $members = array('_GET', '_POST');
    private $store = array();
    public function save() {
        foreach($members as $name) {
            $this->store[$name] = $$name;
            $$name = NULL;
        }
    }
    public function restore() {
        foreach($members as $name) {
            $$name = $this->store[$name];
            $this->store[$name] = NULL;
        }

    }
}

Usage:

$state = new SanddboxState();
$state->save();

// compile your get/post request by setting the superglobals
$_POST['submit'] = 'submit';
...

// execute your script:
$exec = function() {
    include(func_get_arg(0)));
};
$exec('script.php');

// check the outcome.
...

// restore your own global state:
$state->restore();
hakre
  • 193,403
  • 52
  • 435
  • 836
2

dynamic plugin function execution that allows the loaded file and function to execute anything it wants, however it can only take and return variables that can be json_encode'ed.

function proxyExternalFunction($fileName, $functionName, $args, $setupStatements = '') {
  $output = array();
  $command = $setupStatements.";include('".addslashes($fileName)."');echo json_encode(".$functionName."(";
  foreach ($args as $arg) {
    $command .= "json_decode('".json_encode($arg)."',true),";
  }
  if (count($args) > 0) {
    $command[strlen($command)-1] = ")";//end of $functionName
  }
  $command .= ");";//end of json_encode
  $command = "php -r ".escapeshellarg($command);

  exec($command, $output);
  $output = json_decode($output,true);
}

the external code is totally sandboxed and you can apply any permission restrictions you want by doing sudo -u restricedUser php -r ....

user3338098
  • 907
  • 1
  • 17
  • 38
2

Also, you should look at the backtick operator:

$sOutput = `php script_to_run.php`;

This will allow you to inspect the output from the script you are running. However, note that the script will be run with the privileges you have, but you can circumvent this by using sudo on Linux.

This approach also assumes that you have the PHP CLI installed, which is not always the case.

Vegard Larsen
  • 12,827
  • 14
  • 59
  • 102
1

I have developed a BSD-licensed sandbox class for this very purpose. It utilizes the PHPParser library to analyze the sandboxed code, check it against user-configurable whitelists and blacklists, and features a wide array of configuration options along with sane default settings. For your needs you can easily redefine classes called in your sandboxed code and route them to different ones.

The project also includes a sandbox toolkit (use only on your local machine!) that can be used to experiment with the sandbox settings, and a full manual and API documentation.

https://github.com/fieryprophet/php-sandbox

  • Is there anyway to use your class without installing it via composer. I dont want to install it on the live server. Just using the plain classes? – Obaid Maroof Oct 07 '13 at 10:11
0

i know its not 100% topic related, but maybe useful for somebody n__n

function require_sandbox($__file,$__params=null,$__output=true) {

    /* original from http://stackoverflow.com/a/3850454/209797 */

    if($__params and is_array($__params))
     extract($__params);

    ob_start();
    $__returned=require $__file;
    $__contents=ob_get_contents();
    ob_end_clean();

    if($__output)
     echo $__contents;
    else
     return $__returned;

};
AgelessEssence
  • 6,395
  • 5
  • 33
  • 37
  • it doesn't work if $__file tries to define already defined constants. it may also breaks global variables if $__file uses the global keyword or the $GLOBALS array to reference variables in the global scope. – DrLightman Apr 11 '14 at 00:09
  • i updated the code, try it now :D, it is useful for me :D may be not perfect, but is useful for me to require some php files who create vars during their execution that i dont want be in global scope :D – AgelessEssence Apr 11 '14 at 06:50
  • This is more of a template_require, not really a sandbox – Tofandel Apr 07 '21 at 09:52