Онлайн-инструменты для кодеров. Есть ли способ выполнить PHP-код в песочнице из php

  • 03.11.2019

тег список (7)

Для этой цели я разработал BSD-лицензированный класс песочницы. Он использует библиотеку PHPParser для анализа изолированного кода, проверки его против настраиваемых пользователем белых списков и черных списков, а также широкий выбор параметров конфигурации наряду со стандартными настройками по умолчанию. Для ваших нужд вы можете легко переопределить классы, называемые вашим изолированным кодом, и перенаправить их на разные.

Проект также включает в себя инструментарий для песочницы (используется только на вашем локальном компьютере!), Который можно использовать для экспериментов с настройками песочницы, а также полную документацию по ручному и API-интерфейсу.

Я хочу выполнить php-скрипт из php, который будет использовать разные константы и различные версии классов, которые уже определены.

Есть ли песочница php_module, где я мог бы просто:

sandbox ("script.php" ); // run in a new php environment include ("script.php" ); // run in the same environment $sOutput = `php script_to_run.php` ;

Это позволит вам проверять вывод из сценария, который вы используете. Однако обратите внимание, что скрипт будет запущен с вашими привилегиями, но вы можете обойти это, используя sudo в Linux.

Этот подход также предполагает, что у вас установлен CLI PHP, что не всегда так.

Существует Runkit_Sandbox - вы можете заставить его работать, это расширение PHP. Я бы сказал, как идти.

Но вам может понадобиться создать «песочницу» самостоятельно, например, путем сброса состояния глобальной переменной суперглобалов, которые вы используете.

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 ; } } }

Применение:

$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 ();

$cRepo = $em->getRepository("KaleLocationBundle:Country"); // Leave the first array blank $countries = $cRepo->findBy(array(), array("name"=>"asc"));

(PECL runkit >= 0.7.0)

Runkit_Sandbox — Runkit Sandbox Class -- PHP Virtual Machine

Description

Instantiating the Runkit_Sandbox class creates a new thread with its own scope and program stack. Using a set of options passed to the constructor, this environment may be restricted to a subset of what the primary interpreter can do and provide a safer environment for executing user supplied code.

Note : Sandbox support (required for runkit_lint() , runkit_lint_file() , and the Runkit_Sandbox class) is only available as of PHP 5.1.0 or specially patched versions of PHP 5.0, and requires that thread safety be enabled. See the README file included in the runkit package for more information.

Constructor

Runkit_Sandbox::__construct ([ array $options ]) : void

options is an associative array containing any combination of the special ini options listed below.

Runkit_Sandbox class is configured with safe_mode = off , then safe_mode may be turned on for the sandbox environment. This setting can not be used to disable safe_mode when it"s already enabled in the outer script.

Safe_mode_gid

If the outer script which is instantiating the Runkit_Sandbox class is configured with safe_mode_gid = on , then safe_mode_gid may be turned off for the sandbox environment. This setting can not be used to enable safe_mode_gid when it"s already disabled in the outer script.

Safe_mode_include_dir

If the outer script which is instantiating the Runkit_Sandbox class is configured with a safe_mode_include_dir , then a new safe_mode_include_dir may be set for sandbox environments below the currently defined value. safe_mode_include_dir may also be cleared to indicate that the bypass feature is disabled. If safe_mode_include_dir was blank in the outer script, but safe_mode was not enabled, then any arbitrary safe_mode_include_dir may be set while turning safe_mode on.

Open_basedir

open_basedir may be set to any path below the current setting of open_basedir . If open_basedir is not set within the global scope, then it is assumed to be the root directory and may be set to any location.

Allow_url_fopen

Like safe_mode , this setting can only be made more restrictive, in this case by setting it to FALSE when it is previously set to TRUE

Disable_functions

Comma separated list of functions to disable within the sandbox sub-interpreter. This list need not contain the names of the currently disabled functions, they will remain disabled whether listed here or not.

Disable_classes

Comma separated list of classes to disable within the sandbox sub-interpreter. This list need not contain the names of the currently disabled classes, they will remain disabled whether listed here or not.

Runkit.superglobal

Comma separated list of variables to be treated as superglobals within the sandbox sub-interpreter. These variables will be used in addition to any variables defined internally or through the global runkit.superglobal setting.

Runkit.internal_override

Ini option runkit.internal_override may be disabled (but not re-enabled) within sandboxes.

Example #1 Instantiating a restricted sandbox

$options = array(
"safe_mode" => true ,
"open_basedir" => "/var/www/users/jdoe/" ,
"allow_url_fopen" => "false" ,
"disable_functions" => "exec,shell_exec,passthru,system" ,
"disable_classes" => "myAppClass" );
$sandbox = new Runkit_Sandbox ($options );
/* Non-protected ini settings may set normally */
$sandbox -> ini_set ("html_errors" , true );
?>

Accessing Variables

All variables in the global scope of the sandbox environment are accessible as properties of the sandbox object. The first thing to note is that because of the way memory between these two threads is managed, object and resource variables can not currently be exchanged between interpreters. Additionally, all arrays are deep copied and any references will be lost. This also means that references between interpreters are not possible.

Example #2 Working with variables in a sandbox

$sandbox -> foo = "bar" ;
$sandbox -> eval ("echo "$foo\n"; $bar = $foo . "baz";" );
echo " { $sandbox -> bar } \n" ;
if (isset($sandbox -> foo )) unset($sandbox -> foo );
$sandbox -> eval ("var_dump(isset($foo));" );
?>

bar barbaz bool(false)

Calling PHP Functions

Any function defined within the sandbox may be called as a method on the sandbox object. This also includes a few pseudo-function language constructs: eval() , include , include_once , require , require_once , echo , print , die() , and exit() .

Example #3 Calling sandbox functions

$sandbox = new Runkit_Sandbox ();

echo $sandbox -> str_replace ("a" , "f" , "abc" );
?>

The above example will output:

When passing arguments to a sandbox function, the arguments are taken from the outer instance of PHP. If you wish to pass arguments from the sandbox"s scope, be sure to access them as properties of the sandbox object as illustrated above.

Example #4 Passing arguments to sandbox functions

$sandbox = new Runkit_Sandbox ();

$foo = "bar" ;
$sandbox -> foo = "baz" ;
echo $sandbox -> str_replace ("a" , $foo , "a" );
echo $sandbox -> str_replace ("a" , $sandbox -> foo , "a" );
?>

The above example will output:

Changing Sandbox Settings

As of runkit version 0.5, certain Sandbox settings may be modified on the fly using ArrayAccess syntax. Some settings, such as active are read-only and meant to provide status information. Other settings, such as output_handler may be set and read much like a normal array offset. Future settings may be write-only, however no such settings currently exist.

Sandbox Settings / Status Indicators
Setting Type Purpose Default
active Boolean (Read Only) TRUE if the Sandbox is still in a usable state, FALSE if the request is in bailout due to a call to die(), exit(), or because of a fatal error condition. TRUE (Initial)
output_handler Callback When set to a valid callback, all output generated by the Sandbox instance will be processed through the named function. Sandbox output handlers follow the same calling conventions as the system-wide output handler. None
parent_access Boolean May the sandbox use instances of the Runkit_Sandbox_Parent class? Must be enabled for other Runkit_Sandbox_Parent related settings to work. FALSE
parent_read Boolean May the sandbox read variables in its parent"s context? FALSE
parent_write What scope will parental property access look at? 0 == Global scope, 1 == Calling scope, 2 == Scope preceding calling scope, 3 == The scope before that, etc..., etc... 0 (Global)
parent_scope String When parent_scope is set to a string value, it refers to a named array variable in the global scope. If the named variable does not exist at the time of access it will be created as an empty array. If the variable exists but it not an array, a dummy array will be created containing a reference to the named global variable.

Онлайн-сервисы становятся все популярнее, постепенно усложняя функционал и улучшая интерфейсы. В этой подборке представлены онлайн-инструменты для кодеров.

Cloud9

«Это Google Docs, только для кода» - так говорят о проекте. Облачный сервис вырос из Mozilla Bespin. Основные фишки: SSH, drag-and-drop и возможность разработки оффлайн.

Koding (публичная бета)

Koding.com - среда разработки с предустановленным веб-сервером и элементами социальной сети. Этот сервис уже представляли на хабре, топик даже вызвал хабраэффект и нашествие троллей. Сервис до сих пор находится в стадии публичной беты.

CodePen

Инструмент для фронт-энд разработки, позволяющий легко оперировать с CSS/HTML/JS-конструкциями, позволяет подключать js-библиотеки: jQuery, MooTools и т.д. Авторы - Alex Vazquez, Tim Sabat и небезызвестный Chris Coyier.

JSFiddle

Один из самых популярных инструментов для работы с JavaScript/HTML/CSS/SCSS. Прост, удобен, умеет подключать дополнительные библиотеки.

Dabblet

Аналог предыдущего сервиса с достаточно приятным интерфейсом.

Pastebin.me

Сервис для настоящих любителей минимализма - никаких лишних элементов в интерфейсе, только самое нужное, только хардкор.

CSSDesk

CSS-песочница с приятным и удобным интерфейсом.

jsdo.it

Кодинг-сообщество для фронт-энд разработчиков. Подходит для экспериментов с HTML5, WebGL, JavaScript и многим другим - функционал впечатляет.

Tinker

Простая JS/HTML/CSS-песочница.

Tinkerbin

Еще одна простая аналогичная песочница.

SQL Fiddle

Инструмент для работы с SQL-базами от разработчиков с Аляски.

ReFiddle

Сервис для работы с регулярными выражениями на Ruby, JavaScript и.NET.

CSSDeck

Сайт для демонстрации различных CSS-эффектов, можно посмотреть рейтинг самых популярных, там много интересного.

JS Bin

HTML/CSS/JS плюс консоль.

Thimble

Разработка от Mozilla, код и его результат отображается на одной странице в режиме реального времени.

Liveweave

Очень простой в использовании - никакого логина, шаринга, только окна с кодом и результатом.

Google Code Playground

Сервис для работы с Google API.

Compilr

Полноценная среда разработки, интерфейс реализован с использованием всеми любимого фреймворка - Twitter Bootstrap.

Знаете еще подобные сервисы? Пишите в комментарии - добавлю.

), если вам не требуется какое-либо взаимодействие между основным и дочерним процессами.

2

О runkit; это не похоже на песочницу по описанию, или я, может быть, должен сказать легко. Вы можете запретить функции, но я бы предпочел запретить ВСЕ, кроме тех, которые указаны в списке. Если пользователю нужна функция, я могу оценить ее безопасность вручную по запросу. Кажется, единственный способ - написать собственный интерпретатор. Если скорость является проблемой, вы можете заставить ее преобразовать свой АСТ в PHP или другой язык, это на самом деле то, что я собираюсь делать сейчас, поскольку я не мог найти готовое решение. Приветствия! Пс. Да, я видел, что этот Q старый. Ds. - Frank 14 июн. 10 2010-06-14 15:38:55

2

$sOutput = `php script_to_run.php`;

Это позволит вам проверить выход из сценария вы работаете. Однако обратите внимание, что скрипт будет запущен с вашими привилегиями, но вы можете обойти это, используя sudo в Linux.

Этот подход также предполагает, что у вас установлен PHP CLI, что не всегда так.

1

Существует Runkit_Sandbox - Вы могли бы заставить его работать, это расширение PHP. Я бы сказал, как идти.

Но вам может потребоваться создать «песочницу», например, путем сброса состояния глобальной переменной суперглобалов, которые вы используете.

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; } } }

Использование:

$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();

0

я знаю его не 100% темы, связанные, но может быть полезно для кого-то 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; };

0

не работает, если файл $ __ пытается определить уже определенные константы. он также может разбивать глобальные переменные, если файл $ __ использует глобальное ключевое слово или массив $ GLOBALS для ссылки на переменные в глобальной области. - DrLightman 11 апр. 14 2014-04-11 00:09:37

0

i обновил код, попробуйте сейчас: D, это полезно для меня: D может быть не идеальным, но полезно для меня требовать некоторые php-файлы, которые создают vars во время их выполнения, что я не хочу быть в глобальной области: D - AgelessEssence 11 апр. 14 2014-04-11 06:50:20

1

1

динамический модуль выполнения функций, что позволяет загруженный файл и работать, чтобы выполнить все, что он хочет, однако он может только принимать и возвращать переменные, которые могут быть json_encode «под ред.

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 = ")";//end of $functionName } $command .= ");";//end of json_encode $command = "php -r ".escapeshellarg($command); exec($command, $output); $output = json_decode($output,true); }

внешний код полностью песочница, и вы можете применять любые ограничения прав доступа, которые вы хотите, делая sudo -u restricedUser php -r ... .

Я использую create_function для запуска некоторого кода пользователя на сервере. Я ищу любой из этих двух:

  1. Есть ли способ дезинформировать переданный ему код, чтобы предотвратить что-то вредное для выполнения?
  2. Альтернативно, есть ли способ указать, что этот код будет запущен в изолированной среде, чтобы пользователь не мог играть ни с чем другим.

Благодаря!

Вы можете использовать тонкенизатор, чтобы выяснить, что будет делать код, а затем белый список определенных функций и операций. Я думаю, что в конечном итоге это будет очень сложно (или невозможно) сделать его надежным, особенно с учетом гибкости PHP:

$f = "shell_exec"; $arg = "rm -rf /"; $f($arg); // ouch call_user_func($f, $arg); // ouch eval("$f("$arg");"); // ouch $newF = create_user_function("", "$f("$arg");"); $newF(); // ouch

Единственная песочница, которая даст вам 100% -ную защиту (ну, 99,9% …) – это виртуальная машина, которую вы можете просто выбросить.

Мы используем токенизатор для анализа кода статически, а также для изменения кода для выполнения проверок времени выполнения для определенных вещей. Это делается с помощью токенизатора и скриптов, основанных на токенизаторе. Поскольку токенизатор тот же, что использует PHP, он улучшает вашу удачу по написанию собственного.

Я видел людей, использующих регулярные выражения, чтобы попытаться проанализировать язык. Это действительно плохая идея.

Поскольку PHP – довольно глупо-простая грамматика, и у вас есть доступ к токенизатору, вы можете фактически остановить большую часть неудачи, отказавшись от переменных функций и разрешив только небольшое количество белых функций. Если вам не нужен ООП, еще лучше.

Тем не менее, мы не чувствуем себя достаточно уверенно, что мы прибиваем 100% проблем, и мы используем это для питания песочницы для бэкэнд- пользователей, которые платят клиентам, а не каждому пользователю на планете Земля с клавиатурой и, возможно, злой.

Я тоже думаю, что люди здесь, которые poo-poo идею 100%, как «плохая практика», должны понять. Есть основания для этого.

Вы не можете надежно дезинфицировать ввод пользователя – определенный хакер найдет какой-то неясный способ обойти ваш код санитарии.

Песочница может быть возможна, но в равной степени вредна. Если вы действительно хотите быть в безопасности, вы должны создать песочницу для каждого вызова. В конце концов, кто-то может выполнить фальшивый код, который вреден для всех других пользователей вашей песочницы.

Я не думаю, что вы действительно этого хотите. Подумайте об этом так: вы предоставляете программный доступ к серверу!

Вы можете попробовать использовать Quercus, основанный на Java PHP-интерпретатор, для создания безопасной изолированной среды PHP. Вы можете сделать то же самое для JavaScript с помощью Rhino, поэтому я думаю, что это возможно с Quercus.

Вы можете подумать о создании пользовательского (ized) языка, который могут использовать ваши пользователи. Тогда вам решать создать библиотеку поддерживаемых функций, которые вполне могут быть просто оболочками собственных функций PHP. Но даже тогда, делая его взломанным или просто работающим, в лучшем случае это утомительная работа. Возможно, вам следует переоценить, почему вы хотите, чтобы пользователи имели доступ к коду в первую очередь? Я бы хотел помочь, если вам нужен кто-то, чтобы обсудить это с (или обновить свой вопрос, я думаю? 🙂

Надеюсь, вы сможете это исправить!

В целом плохая идея и слишком опасная ИМО, независимо от того, какую защиту вы вводите в действие. Лучше создать псевдоязык, ограниченный только тем, что пользователям разрешено делать.