15

I would like to make something like tryruby.org. I take a line from the user (e.g., echo __FILE__) and I want to execute it in PHP and return the output back to the client.

I tried to do exec('php -r ' . $command, $output), but $output always contains the PHP help section.

How can I implement this feature?

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
balkon_smoke
  • 1,136
  • 2
  • 10
  • 25
  • Try `exec("php -r \"$command\"", $output)`. BUt at any case its too dangerous make users can run command on your machine – safarov Apr 05 '12 at 08:45
  • Take a look at `eval` http://php.net/manual/en/function.eval.php but I wouldn't recommend just putting anything from the user in there. You would want to heavily filter it out beforehand. – Nick Apr 05 '12 at 08:46
  • 2
    Better yet, take a look at [`Runkit_Sandbox`](http://de2.php.net/manual/en/runkit.sandbox.php). – vstm Apr 05 '12 at 08:48
  • It will be specific list of commands users allowed to type – balkon_smoke Apr 05 '12 at 08:48

4 Answers4

27

To make php -r you have to have to put the code you want to execute between ' .. your code .. '

Example:

php -r ' $var = 34; print_r($var); '
Andreas Helgegren
  • 1,640
  • 12
  • 11
7

It looks like your problem is that you aren't wrapping your code to be executed with ' '. You also need to be wary of ' in the code, special characters, escape sequences, etc.

In fact, if you insist on using exec(), it might be better to do this (to completely avoid having to worry about escaping and the such):

$command = base64_encode($command);
exec("php -r 'eval(base64_decode(\"$command\"));'", $output);

You could use eval() instead of what you're posting above.

The main issue here (both with eval() and your exec() code) is that taking PHP code from user input simply isn't safe:

The eval() language construct is very dangerous because it allows execution of arbitrary PHP code. Its use thus is discouraged. If you have carefully verified that there is no other option than to use this construct, pay special attention not to pass any user provided data into it without properly validating it beforehand.

Suggestion

Since you want to return the result of the PHP code, you could potentially do something cool with Ajax, where you pass the PHP code to a script (Base64 encoded, perhaps) as a parameter:

$code = base64_decode($_GET['code']);
// Clean the user input here
eval($code);

Ajax example using jQuery:

// assuming `code` contains the PHP code
var encoded = base64_enc(code);

$.get('execute.php?code=' + encoded, function(data) {
    var result = new String(data);
    // do something with the result here, such as displaying it
}, dataType='text');

For Base64 encoding in JavaScript, see this.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Xenon
  • 3,174
  • 18
  • 37
1

http://tryruby.org seems have an interactive Ruby shell. That seems to be a good starting point.

Here are two projects that provide such a shell for PHP: php_repl and phpsh.

The other part is the web interface for the interactive shell. For that part, I suggest you have a look at repl.it, which provides this service for many languages (but sadly not PHP). Here's a link to it's source code.

With this combination, you should be able to complete cour project.

Carsten
  • 17,991
  • 4
  • 48
  • 53
-1

Look up 'eval()' and more importantly, why eval() and what you're trying to do is very difficult to achieve in a secure manner. Imaging for example the user who inputs:

echo file_get_contents('/etc/passwd');

You'll need quite a bit of work to make this secure, including watching and filtering all system calls being made from the eval'd process.

Cheers

smassey
  • 5,875
  • 24
  • 37