8

I want to secure my PHP installation. I can disable some functions, like system(), exec() etc using disable_functions in php.ini. But I can forget to disable some dangerous functions. Is it possible to disable all functions, excluding the ones already used in my application?

7
  • 1
    I don't think this is possible with standard PHP.
    – deviantfan
    May 5, 2016 at 7:43
  • 5
    +1 for wanting to use a whitelist rather than a blacklist. I wish more people thought like you :-) May 5, 2016 at 7:50
  • How do you determine which functions aren't dangerous?
    – hspaans
    May 5, 2016 at 9:17
  • hspaans, I want to minimize privileges of PHP scripts. So I am looking for a way to disable all PHP functions, which are not used by my application, not just several functions.
    – checkbox
    May 5, 2016 at 9:38
  • 1
    @Crecket PHP doesn't have that many functions. 1026 on my machine. You can easily put them all into the blacklist and then go through it and delete all of the entries of the functions you want to use without too much trouble. Actually, this would probably be faster than attempting to list all of the functions you want to use.
    – UTF-8
    May 5, 2016 at 12:24

2 Answers 2

3

To hook into @UTF-8's comment, using PHP_Parser, you can fairly easily generate a list of default PHP functions not actually used by your application which you can then store in the disabled_functions configuration option:

<?php

require 'vendor/autoload.php';

use PhpParser\Node;
use PhpParser\NodeTraverser;
use PhpParser\ParserFactory;
use PhpParser\NodeVisitorAbstract;
use PhpParser\PrettyPrinter\Standard;
use PhpParser\Node\Stmt\Class_;
use PhpParser\Node\Stmt\Function_;


class Collector extends NodeVisitorAbstract
{
    public $functions = [];
    public function leaveNode(Node $node)
    {
        if ($node instanceof PhpParser\Node\Expr\FuncCall)
            $this->functions[] = (string) $node->name;
    }
}

$sourcePath = __DIR__ . '/test/';

$files = new \CallbackFilterIterator(
    new \RecursiveIteratorIterator(
        new \RecursiveDirectoryIterator($sourcePath),
            \RecursiveIteratorIterator::SELF_FIRST
    ),
    function($current, $key, $iterator) { return preg_match('~.php$~i', (string) $current) > 0; }
);

$nodeTraverser = new NodeTraverser();
$nodeTraverser->addVisitor($visitor = new Collector());
$parserFactory = new ParserFactory();
$parser        = $parserFactory->create(ParserFactory::PREFER_PHP7);

foreach ($files as $file) 
{


    $stmts  = $parser->parse(file_get_contents((string) $file));
    $nodeTraverser->traverse($stmts);
}

$defined_functions = get_defined_functions();

$blocked_functions = array_diff($defined_functions['internal'], $visitor->functions);

echo 'disabled_functions = "', join(',', $blocked_functions), '"', PHP_EOL;

Something similar can be created for disable_classes, just look for PhpParser\Node\Expr\New_ instead.

Some things to consider:

  • Your first step should be to reduce the amount of modules your instance of PHP is loading.
  • It's going to be annoying to manage this.
  • You're going to have a bad time if you use anything dynamically.
  • Having a large disable_functions setting may have a performance impact. You may want to consider using Suhosin's whitelist functionality as suggested by https://security.stackexchange.com/a/122471/242.
2

You can use Suhosin extension which allows you to whitelist functions that you want to allow.

See Suhosin's suhosin.executor.func.whitelist configuration option.

suhosin.executor.func.whitelist

Comma separated whitelist of functions that are allowed to be called. If the whitelist is empty the blacklist is evaluated, otherwise calling a function not in the whitelist will terminate the script and get logged.

Note: This setting deactivates suhosin.executor.func.blacklist.


Suhosin (pronounced 'su-ho-shin') is an advanced protection system for PHP installations. It was designed to protect servers and users from known and unknown flaws in PHP applications and the PHP core. Suhosin comes in two independent parts, that can be used separately or in combination. The first part is a small patch against the PHP core, that implements a few low-level protections against buffer overflows or format string vulnerabilities and the second part is a powerful PHP extension that implements numerous other protections.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .