A full-scale PHP sandbox class that utilizes PHP-Parser to prevent sandboxed code from running unsafe code

Overview

PHPSandbox

A full-scale PHP 7.4+ sandbox class that utilizes PHP-Parser to prevent sandboxed code from running unsafe code.

It also utilizes FunctionParser to disassemble callables passed to the sandbox, so that PHP callables can also be run in sandboxes without first converting them into strings.

Manual: https://manual.phpsandbox.org

Online API Documentation: https://docs.phpsandbox.org

Latest Stable Version Total Downloads Latest Unstable Version License Dependency Status PHP Composer

Features:

  • Finegrained whitelisting and blacklisting, with sensible defaults configured.
  • Includes dynamic demonstration system that allows for local testing of custom sandbox configurations
  • Can redefine internal PHP and other functions to make them more secure for sandbox usage.
  • Can redefine superglobals and magic constants to expose your own values to sandboxed code.
  • Can overwrite the get_defined_* and get_declared_* functions to show only allowed functions, classes, etc. to the sandboxed code.
  • Can selectively allow and disallow function creation, class declarations, constant definitions, keywords, and much more.
  • Can prepend and append trusted code to setup and tear down the sandbox, and automatically whitelist the classes, functions, variables, etc. they define for the sandbox.
  • Can retrieve the generated sandbox code for later usage.
  • Can pass arguments directly to the sandboxed code through the execute method to reveal chosen outside variables to the sandbox.
  • Can access the parsed, prepared and generated code ASTs for further analysis or for serialization.
  • Can define custom validation functions for fine-grained control of every element of the sandbox.
  • Can specify a custom error handler to intercept PHP errors and handle them with custom logic.
  • Can specify a custom exception handler to intercept thrown exceptions and handle them with custom logic.
  • Can specify a validation error handler to intercept thrown validation errors and handle them with custom logic.
  • Can intercept callbacks and validate them against function whitelists and blacklists, even if they are called as strings

Example usage:

function test($string){
    return 'Hello ' . $string;
}

$sandbox = new PHPSandbox\PHPSandbox;
$sandbox->whitelistFunc('test');
$result = $sandbox->execute(function(){
    return test('world');
});

var_dump($result);  //Hello world

Custom validation example:

setFuncValidator(function($function_name, PHPSandbox\PHPSandbox $sandbox){ return (substr($function_name, 0, 7) == 'custom_'); //return true if function is valid, false otherwise }); $sandbox->execute(function(){ custom_func(); }); //echoes "I am valid!"">
function custom_func(){
    echo 'I am valid!';
}

$sandbox = new PHPSandbox\PHPSandbox;
//this will mark any function valid that begins with "custom_"
$sandbox->setFuncValidator(function($function_name, PHPSandbox\PHPSandbox $sandbox){
    return (substr($function_name, 0, 7) == 'custom_');  //return true if function is valid, false otherwise
});
$sandbox->execute(function(){
    custom_func();
});
//echoes "I am valid!"

Custom validation error handler example:

$sandbox = new PHPSandbox\PHPSandbox;
//this will intercept parser validation errors and quietly exit, otherwise it will throw the validation error
$sandbox->setValidationErrorHandler(function(PHPSandbox\Error $error, PHPSandbox\PHPSandbox $sandbox){
    if($error->getCode() == PHPSandbox\Error::PARSER_ERROR){ //PARSER_ERROR == 1
        exit;
    }
    throw $error;
});
$sandbox->execute('');
//does nothing

Disable validation example:

'); //Pinging google.com. . .">
$sandbox = new PHPSandbox\PHPSandbox;
//this will disable function validation
$sandbox->setOption('validate_functions', false); // or $sandbox->validate_functions = false;
$sandbox->execute('');
//Pinging google.com. . .

Requirements

  • PHP 7.4+
  • PHP-Parser
  • FunctionParser (if you wish to use closures)
  • PHP should be compiled with --enable-tokenizer option (it typically is)

Installation

To install using composer, simply add the following to your composer.json file in the root of your project:

{
    "require": {
        "corveda/php-sandbox": "3.*"
    }
}

Then run composer install --dry-run to check for any potential problems, and composer install to install.

LICENSE

Copyright (c) 2013-2021 by Corveda, LLC.

Some rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:

    * Redistributions of source code must retain the above copyright
      notice, this list of conditions and the following disclaimer.

    * Redistributions in binary form must reproduce the above
      copyright notice, this list of conditions and the following
      disclaimer in the documentation and/or other materials provided
      with the distribution.

    * The names of the contributors may not be used to endorse or
      promote products derived from this software without specific
      prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Comments
  • Update nikic/php-parser to latest version

    Update nikic/php-parser to latest version

    Hello,

    Is there anything preventing you from using the latest version of nikic/php-parser (v.4)? We have other dependencies in our projects which require the newer version (at least version 3) and we are having troubles with that.

    opened by iskren-dimov 3
  • Fix issues with closures, traits, aliases, and interfaces

    Fix issues with closures, traits, aliases, and interfaces

    Just started using this project and found that traits and closures were unusable.

    For traits, aliases, and interfaces, I found that the name of the trait was always passed to the visitor as Node\Identifier, not string, but included both for BC. Maybe a change in PHPParser?

    For closures, the $name instanceof checks in checkFunc could never be reached because of the function's type hint.

    Sorry to lump them in one PR but that's how I committed it in my fork. I've added test coverage for both cases as well. Thanks!

    opened by mortenson 2
  • Is it possible to redefine eval

    Is it possible to redefine eval

    I need to log every arguments before eval statement is executed. I know eval is a language construct, but still cant find a way to rewrite it.

    The attempts gives me error message as below: eval()'d code(3) : eval()'d code on line 1

    So the question is, is it possible to rewrite a keyword or could I place a filter before eval is executed.

    opened by forfrt 2
  • Update composer.json

    Update composer.json

    Composer:

    Deprecation warning: require.jeremeamia/FunctionParser is invalid, it should not contain uppercase characters. Please use jeremeamia/functionparser instead.

    opened by WinterSilence 1
  • Can I use for customize reports generators?

    Can I use for customize reports generators?

    I have many customers and each one need a customizate reports. It's inviable create one code report to each one.

    I think to create a report crud with a text editor box, in this box I will write the php code to run in phpSandbox (with restric environment obviosly) to agroup the mysql results (sql query would run out of sandbox and inject the result in phpSandbox) and build the report as my costumer wish.

    Conclusion: I would use the phpSandbox(with restric environment) only to handle the pdf/excel generator to build the report.

    Could I do that? Could have any security problem?

    Code to run in sandbox:

    $registers = sort($mysqlResultsInjected);
    
    $excel = new Excel();
    
    foreach($registers as $register) {
       $excel->row([$register->id, $register->name]);
    }
    
    $excel->output();
    
    
    opened by LuanMaik 1
  • Safe to run user's input code

    Safe to run user's input code

    I plan to use this library to run user's input code in isolated environment with most functions blacklisted by default. (On some relatively safe string and array manipulation). I wonder if there is any security that I should consider? I can imagine that all the SERVER, SESSION variables should be blacklisted or overriden as well?

    opened by yellow1912 1
  • Declare Global vars inside the Sandbox, and make them available only there...

    Declare Global vars inside the Sandbox, and make them available only there...

    Hi, is it possible to Declare Global vars inside the Sandbox, and make them available only there...? I need this because i want to execute a lot of functions using same global vars => but i need to execute them in multithreading environment, so don't need them to access same var with same memory stack (same pointer), need to separate them without changing the Arhitecture and classes...

    opened by DrOctavius 1
  • Run sandbox PHP code on multiple PHP versions

    Run sandbox PHP code on multiple PHP versions

    I came across this online PHP sandbox app similar to this project (closed source and not available except as an online service) http://sandbox.onlinephpfunctions.com/

    I noticed it allows to run the PHP code on up to 62-63 different PHP versions!

    I am curious, would it be difficult to allow a project like this to work across multiple PHP versions? I realize it would likely require the hosting server to have all the available PHP versions installed but was just curious if it might be easy to add support for this project to work across multiple versions when available?

    opened by jasondavis 1
  • Possibble to use PHP's DateTime class?

    Possibble to use PHP's DateTime class?

    Running this code $TwoWeeksAgo = new DateTime(date("Ymd"));

    on the demno here https://code.phpsandbox.org/ results in this error message:

    Sandboxed code attempted to call invalid type: DateTime

    Is there a way to make this work?

    opened by jasondavis 1
  • Carrying a context through multiple executions

    Carrying a context through multiple executions

    I was able to get my idea working with plain eval. See the code below:

    function staticEval($_code)
    {
        static $_vars = [];
        extract($_vars);
        $_result = eval($_code);
        $_vars = get_defined_vars();
        unset($_vars['_vars']);
        unset($_vars['_code']);
        unset($_vars['_result']);
        return $_result;
    }
    
    staticEval('$a = "hello world!";');
    staticEval('echo "$a\n";');
    
    opened by datashaman 1
  • How to redefine a internal function

    How to redefine a internal function

    It says in the introduction that:

    Can redefine internal PHP and other functions to make them more secure for sandbox usage.

    So I have tried using defineFunc like below:

             $newSandbox=$this->sandbox->defineFunc("phpinfo", function(){
                 echo "hellow phpinfo";
             });
             $newSandbox->whitelistFunc('phpinfo');
             #printHello('1\n');
             $newSandbox->execute(function(){
                 phpinfo();
             });
    

    But it seems doesn't work fine with eval statement. Furthermore, Could I have any method to inherit internal function other than totally rewrite it.

    Best regrads.

    opened by forfrt 1
  • defineFunc mangles callables

    defineFunc mangles callables

    https://github.com/Corveda/PHPSandbox/blob/main/src/PHPSandbox.php#L2670

    If you attempt to pass a non-static method callable in, for instance: [$instance, 'methodName'] it passes the callable typehint, then gets nuked by whatever that condition block is all about, and then throws an exception about being uncallable. Why?

    And attempting to pass a nested array does not pass the callable typehint. I can workaround this by passing a closure to perform the same work, but this is still an issue.

    In theory this would also break static class method calls in array syntax as well, possibly leading to bizarre or even dangerous behavior if the class name is still callable or invokable.

    If instance methods are unsupported or otherwise should not be used, they should be checked for properly. Please do not mangle my callable.

    opened by edhaase 0
  • Callable string variable invalid operations

    Callable string variable invalid operations

    When a variable is passed to a function, the sandbox wraps it with a "wrap" function. If the variable is a string with a callable value like "time", the "wrap" function returns a SandboxedString object. The target function receives the SandboxedString object instead of the string. Understand that the SandboxedString object was trying to prevent unsafe code to run by a callable variable. However, it has following issues.

    1. The gettype function in the target function returns "object" instead of "string". The var_dump and var_export functions are okay.
    2. Strict comparison of input values in the target function fail because they are objects instead of strings.
    3. I don't know if this could have any security concern because the SandboxedString passed into custom function contains a lot of information.

    Following code replicates the issue. The gettype in obj_b->getValue returns "object". The strict comparison in obj_a->test returns "false" even the same strings are submitted to the function.

    echo '001';
    echo '<br>';
    
    $execode = '';
    $appcode = '';
    
    $execode = 'class obj_a {' .
    			'	function test($x, $y, $cusfun) {' .
    			'		$a = $cusfun[\'b\']->getValue($x);' .
    			'		$b = $cusfun[\'b\']->getValue($y);' .
    			'		return ($a === $b);' .
    			'	}' .
    			'}' .
    			'class obj_b {' .
    			'	function getValue($x) {' .
    			'		echo gettype($x) . \'<br>\';' .
    			'		return $x;' .
    			'	}' .
    			'}' .
    			'$cusfun[\'a\'] = new obj_a();' .
    			'$cusfun[\'b\'] = new obj_b();';
    			
    $appcode = 'return $cusfun;';
    
    echo '002';
    echo '<br>';
    
    $sandboxcusfun = new PHPSandbox\PHPSandbox;
    
    $sandboxcusfun->setOptions(['allow_classes'=>1]);
    $sandboxcusfun->defineVar('cusfun',null);
    
    $cusfun = $sandboxcusfun->execute($execode . $appcode);
    
    echo '003';
    echo '<br>';
    var_dump($cusfun);
    echo '<br>';
    
    $r = 'nothing';
    if ($cusfun['a'] && method_exists($cusfun['a'], 'test')) {
    	$r = $cusfun['a']->test('ob_clean','ob_clean',$cusfun);
    }
    
    echo '005';
    echo '<br>';
    
    var_dump($r);
    echo '<br>';
    
    echo '006';
    echo '<br>';
    
    opened by etmpoon 2
  • Wrong results when an element in an array, has a function name

    Wrong results when an element in an array, has a function name

    For example :

    $sandbox = new PHPSandbox; function test ($values) { return $values; } $sandbox->whitelistFunc(['test','dd']); $sandbox->allow_casting = true;

    $result = $sandbox->execute(function(){ return test(['required','date', 'copy']); });

    print_r( $result , );

    opened by mustafaeida 4
  • Code with argument unpacking not working

    Code with argument unpacking not working

    Code:

    function foo(int ...$a) {
    	return $a;
    }
    
    $ints = [1,2];
    foo(...$ints);
    

    Result: Compile Error: Cannot use positional argument after argument unpacking

    Generated code causing the error:

    return foo(\PHPSandbox\wrapByRef(...$ints, \PHPSandbox\PHPSandbox::getSandbox('__PHPSandbox_ff7c8ab064063e1d4d509dfbadda498e')));
    
    opened by Furgas 0
  • Fatal error: Cannot use isset() on the result of an expression

    Fatal error: Cannot use isset() on the result of an expression

    PHPSandbox throws an error if there's a check for a superglobal variable.

    The code:

    <?php
    isset($_SERVER);
    ?>
    

    The error message:

    Fatal error: Cannot use isset() on the result of an expression (you can use "null !== expression" instead) in /.../vendor/corveda/php-sandbox/src/PHPSandbox.php(6885) : eval()'d code on line 8
    
    opened by asabirov 0
  • Type checks in use statements and parameter type hints

    Type checks in use statements and parameter type hints

    I've extended the code to check for whitelisted types and interfaces in parameter type hints and use statements. Even though this is not strictly required for practical sandbox constraints; for my use of this library this is very helpful. I'm not sure if this breaks other use cases; if so I can add a switch.

    opened by LukasRos 2
Releases(v3.0.1)
Owner
Corveda
Provider of web applications and services.
Corveda
PHP Static Analysis Tool - discover bugs in your code without running it!

PHPStan - PHP Static Analysis Tool PHPStan focuses on finding errors in your code without actually running it. It catches whole classes of bugs even b

PHPStan 11.6k Dec 30, 2022
A PHP parser written in PHP

PHP Parser This is a PHP 5.2 to PHP 8.0 parser written in PHP. Its purpose is to simplify static code analysis and manipulation. Documentation for ver

Nikita Popov 15.9k Jan 3, 2023
A web tool to explore the ASTs generated by PHP-Parser.

phpast.com A web tool to explore the ASTs generated by PHP-Parser. About This web tool provides a GUI for exploring the AST of your PHP code. You can

Ryan Chandler 23 Nov 29, 2022
A generic content parser based on the devto markdown + frontmatter format, with liquid tag support

Parsed A generic content parser based on the devto post format, with front matter and liquid tag support. Parsed uses league/commonmark as base markdo

null 18 Dec 28, 2022
TypeResolver - A PSR-5 based resolver of Class names, Types and Structural Element Names

TypeResolver and FqsenResolver The specification on types in DocBlocks (PSR-5) describes various keywords and special constructs but also how to stati

phpDocumentor 9k Dec 29, 2022
Library for counting the lines of code in PHP source code

sebastian/lines-of-code Library for counting the lines of code in PHP source code. Installation You can add this library as a local, per-project depen

Sebastian Bergmann 715 Jan 5, 2023
Provides functionality that helps writing PHP code that has runtime-specific (PHP / HHVM) execution paths

sebastian/environment This component provides functionality that helps writing PHP code that has runtime-specific (PHP / HHVM) execution paths. Instal

Sebastian Bergmann 6.5k Jan 3, 2023
Search PHP source code for function & method calls, variables, and more from PHP.

Searching PHP source code made easy Search PHP source code for function & method calls, variable assignments, classes and more directly from PHP. Inst

Permafrost Software 22 Nov 24, 2022
A PHP code-quality tool

GrumPHP Sick and tired of defending code quality over and over again? GrumPHP will do it for you! This composer plugin will register some git hooks in

PHPro 3.9k Jan 1, 2023
Copy/Paste Detector (CPD) for PHP code.

PHP Copy/Paste Detector (PHPCPD) phpcpd is a Copy/Paste Detector (CPD) for PHP code. Installation This tool is distributed as a PHP Archive (PHAR): $

Sebastian Bergmann 2.2k Jan 1, 2023
Analyze PHP code with one command

PHPQA Analyze PHP code with one command. Requirements PHP >= 5.4.0 xsl extension for HTML reports Why? Every analyzer has different arguments and opti

edgedesign/phpqa 542 Dec 24, 2022
Performs advanced static analysis on PHP code

PHP Analyzer Please report bugs or feature requests via our website support system ? in bottom right or by emailing [email protected]. Contri

Continuous Inspection 443 Sep 23, 2022
A static php code analysis tool using the Graph Theory

Mondrian Ok guyz, you have a master degree in Graph Theory, you follow Law of Demeter and you live on S.O.L.I.D principles ? Let's have some Fun ! (^ω

Florent Genette 391 Nov 30, 2022
Instant Upgrades and Instant Refactoring of any PHP 5.3+ code

Rector - Speedup Your PHP Development Rector helps you with 2 areas - major code changes and in daily work. Do you have a legacy code base? Do you wan

RectorPHP 6.5k Jan 8, 2023
Deptrac is a static code analysis tool for PHP that helps you communicate, visualize and enforce architectural decisions in your projects

Deptrac is a static code analysis tool for PHP that helps you communicate, visualize and enforce architectural decisions in your projects. You can freely define your architectural layers over classes and which rules should apply to them.

QOSSMIC GmbH 2.2k Dec 30, 2022
phpcs-security-audit is a set of PHP_CodeSniffer rules that finds vulnerabilities and weaknesses related to security in PHP code

phpcs-security-audit v3 About phpcs-security-audit is a set of PHP_CodeSniffer rules that finds vulnerabilities and weaknesses related to security in

Floe design + technologies 655 Jan 3, 2023
A tool to automatically fix PHP Coding Standards issues by Dragon Code.

A tool to automatically fix PHP Coding Standards issues by Dragon Code.

The Dragon Code 24 Aug 27, 2022
PHP code scanner to use with gettext/gettext

PHP code scanner to use with gettext/gettext

Gettext 12 Nov 11, 2022
Code Climate CLI

Code Climate CLI Overview codeclimate is a command line interface for the Code Climate analysis platform. It allows you to run Code Climate engines on

Code Climate 2.4k Dec 26, 2022