Реализация онлайн-среды для PHP скриптов: от простого к защищенному

Раздел: Веб-разработка -> Инструменты разработчика

Основные подходы к онлайн-выполнению PHP

Как выполнить PHP код на сервере с минимальными рисками?

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


<?php
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['code'])) {
    $code = $_POST['code'];
    // Создание временного файла
    $tmpfile = tempnam(sys_get_temp_dir(), 'php_') . '.php';
    file_put_contents($tmpfile, '<?php ' . $code);
    // Формирование команды с ограничениями
    $timeout = 5;
    $disabled = 'exec,system,popen,proc_open,shell_exec,pcntl_exec,ini_restore';
    $cmd = sprintf('php -d display_errors=1 -d error_reporting=E_ALL -d max_execution_time=%d -d disable_functions=%s -f %s 2>&1', $timeout, $disabled, escapeshellarg($tmpfile));
    $descriptorspec = [
        0 => ['pipe', 'r'],
        1 => ['pipe', 'w'],
        2 => ['pipe', 'w']
    ];
    $process = proc_open($cmd, $descriptorspec, $pipes);
    if (is_resource($process)) {
        fclose($pipes[0]);
        $output = stream_get_contents($pipes[1]);
        $error = stream_get_contents($pipes[2]);
        fclose($pipes[1]);
        fclose($pipes[2]);
        proc_close($process);
    }
    unlink($tmpfile);
    // Вывод результата
    if ($error) echo "<pre class=\"ex_r\">Ошибка: $error</pre>";
    if ($output) echo "<pre class=\"ex_r\">$output</pre>";
}
?>

Пояснение шагов: Сначала создается временный файл с кодом. Затем используется proc_open для запуска php с флагами -d, которые переопределяют настройки php.ini. max_execution_time ограничивает время выполнения, disable_functions отключает потенциально опасные функции. Вывод и ошибки захватываются через pipes.

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

Типичная ошибка: При использовании `exec` вместо proc_open нарушается захват STDERR, а также увеличивается риск блокировки.

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

Как обеспечить полную изоляцию с помощью контейнеризации?

Использование Docker позволяет запускать код в изолированном контейнере, который не влияет на хост-систему. Пример команды для выполнения кода из строки:

echo '<?php echo "Hello, Docker!";' | docker run -i --rm php:cli php

Для передачи файла можно смонтировать временный каталог. Проблемы: требуется установленный Docker и демон, время запуска контейнера (первые миллисекунды).

Ошибка: Неверное указание образа (php:cli без тега может привести к загрузке нежелательной версии). Рекомендуется указывать версию, например php:8.2-cli.

Цель: выполнение кода в полностью изолированной среде с возможностью установки любых расширений.

Какие готовые сервисы позволяют выполнять PHP код онлайн без установки?

Существуют сайты, предоставляющие возможность запуска PHP кода. Например, 3v4l.org (проверка кода на многих версиях PHP), onlinephp.io (простой интерфейс), PHP Tester. Они безопасны для тестирования, но не подходят для проектов с коммерческой информацией.

Проблемы: Зависимость от внешнего сервиса, ограничение на время выполнения и размер кода, отсутствие доступа к файловой системе.

Цель: быстрая проверка синтаксиса или демонстрация кода без настройки окружения.

Как программно создать песочницу для PHP с помощью специальной библиотеки?

Библиотека PHPSandbox позволяет выполнять PHP код в виртуальном пространстве с ограниченными функциями, переменными и доступом. Пример использования:

require 'vendor/autoload.php';
use function PHPSandbox\sandbox;
$result = sandbox(function(){
    echo "Это выполняется в песочнице";
    // не доступны опасные функции
});
echo $result;

Проблемы: библиотека использует переопределение функций через расширение, требует PHP 7.0+ и не поддерживает все возможности.

Ошибка: Если опасная функция не переопределена, код может быть небезопасен. Необходимо настраивать белый список функций.

Цель: встраивание ограниченного выполнения в приложение (например, для пользовательского кода).

Расширенные примеры и результаты

Полный пример веб-интерпретатора с формой

Ниже представлен полный HTML-файл, который содержит форму для ввода кода и отображает результат выполнения. Используется обработчик на основе proc_open с ограничениями.

Пример

<!DOCTYPE html>
<html lang="ru">
<head>
    <meta charset="UTF-8">
    <title>PHP Online Runner</title>
</head>
<body>
    <h2>Выполнение PHP кода</h2>
    <form method="post">
        <textarea name="code" rows="10" cols="60"><?php echo 'Привет, мир!'; ?></textarea><br>
        <input type="submit" value="Запустить">
    </form>
    <div style="border:1px solid #ccc; padding:10px; margin-top:10px;">
        <h3>Результат:</h3>
        <?php
        // Здесь вставляется код обработчика из основного решения
        // (proc_open с временным файлом)
        // Для краткости код не дублируется, предполагается его наличие
        ?>
    </div>
</body>
</html>

Если ввести <?php echo 'Привет, мир!'; ?>, результатом будет:

Привет, мир!

Пример с Docker и временным файлом

Создание временного PHP-файла и его выполнение в контейнере с монтированием:

Пример

#!/bin/bash
# Создаем временный файл
cat > /tmp/test.php << 'EOF'
<?php
$data = [1,2,3];
echo array_sum($data);
EOF
# Запуск контейнера с монтированием
docker run --rm -v /tmp/test.php:/code.php php:8.2-cli php /code.php

Результат выполнения в контейнере:

6

Пример с PHPSandbox с настройками

Установка прав доступа и белого списка функций:

Пример

require 'vendor/autoload.php';

use PHPSandbox\Sandbox;

$sandbox = new Sandbox();
$sandbox->setErrorReporting(E_ALL);
$sandbox->setExecutionTime(3);
$sandbox->whitelistFunc('echo', 'print', 'var_dump', 'count');

$code = 'echo "Сумма: " . (2+3);';
$result = $sandbox->execute($code);

echo $result;

Результат:

Сумма: 5

Обработка ошибок и исключений

При выполнении кода с ошибкой (например, деление на ноль) необходимо корректно отображать сообщение. В обработчике через proc_open ошибки захватываются в STDERR. Пример:

Пример

<?php
$code = 'echo 1/0;';
// ... обработка (как в rbase) ...
// вывод ошибки
?>

Результат:

Warning: Division by zero in /tmp/php_XXXXXX.php on line 2

Это позволяет разработчику видеть полную диагностику.

PHP файл онлайн - comments

En
Php файл онлайн (php)