5

I'm trying to disable functions, in my apache2 config file, but it's not working for some reason. I've verified that other php_admin_value settings ARE working, but it's just ignoring disable_functions

Here's what I have:

<Directory "/var/www/testdir/*">

php_admin_value open_basedir "/var/www/testdir"
php_admin_value disable_functions "exec,shell_exec"

</Directory>

The open_basedir admin value is working as expected (cannot include '../something'), but yet, it will still exec ls -a .. or let me exec('ls -a ..', $output); echo $output; as if the disable_functions flag was not even set.

Any ideas on how to fix this?

Eva
  • 4,859
  • 3
  • 20
  • 26

4 Answers4

8

disable_functions can only be changed in the php.ini file:

Name                Default Changeable          Changelog
disable_functions   ""      PHP_INI_SYSTEM only Available since PHP 4.0.1.

However, php_admin_value can not be used in an .htaccess file.

Gumbo
  • 643,351
  • 109
  • 780
  • 844
  • does this mean the only way to go about things is with fpm? – Eva Oct 20 '13 at 13:45
  • @Evan What do you mean by “fpm”? – Gumbo Oct 20 '13 at 14:32
  • http://www.php.net/manual/en/install.fpm.php - unless of course there is a way of disabling functions by directory ("suhosin" appears to be an option but not supported in PHP5.4) – Eva Oct 20 '13 at 14:47
  • @Evan Where do you use the mentioned directives? – Gumbo Oct 20 '13 at 16:23
  • I put it in the apache2.conf file (through an include) – Eva Oct 20 '13 at 16:35
  • @Evan In that case it should work, though. Did you try it without the `*` in `/var/www/testdir/*`? Because I think `/var/www/testdir/*` will only match sub-directories of `/var/www/testdir` and not `/var/www/testdir` itself. – Gumbo Oct 20 '13 at 16:55
  • It is a little sad to read that there seems to be no way in PHP to allow for "priviledge dropping" outside of php.ini. Considering the huge functionality and incurred risks of PHP it would make most sence to allow to disable functions. sometimes I think vulnerability is a key feature of PHP ;) – humanityANDpeace Mar 14 '14 at 12:15
  • "However, php_admin_value can only change PHP_INI_ALL and PHP_INI_PERDIR changeable configuration options." This is incorrect. php_admin_value simply can't be used in .htaccess or httpd.conf, but it can modify PHP_INI_SYSTEM variables when used elsewhere – Olivier - interfaSys Sep 17 '14 at 09:09
  • @Olivier-interfaSys You’re right, I have changed that. – Gumbo Sep 17 '14 at 09:20
2

I disagree with Gumbo. You can definitely modify the disable_function from the php.ini. BUT the caveat is you can NOT override what is already defined. You can only append to that array. For example if your php.ini file had nothing for disable_functions, you could append:

php_admin_value[disable_functions] = link,symlink,popen,exec,system,shell_exec,show_source,passthru,pcntl_alarm,pcntl_fork,pcntl_waitpid,pcntl_wait,pcntl_wifexited,pcntl_wifstopped,pcntl_wifsignaled,pcntl_wexitstatus,pcntl_wtermsig,pcntl_wstopsig,pcntl_signal,pcntl_signal_dispatch,pcntl_get_last_error,pcntl_strerror,pcntl_sigprocmask,pcntl_sigwaitinfo,pcntl_sigtimedwait,pcntl_exec,pcntl_getpriority,pcntl_setpriority

The flip side of that is, that if you php.ini file had say popen disabled, you could not override it by use of the php_admin_value.

I played with this for a bit trying on php 5.5.9 to get to the bottom of an issue. I tried overriding a the php value for disable_function. While a phpinfo() showed the disable_function line as empty after my over-ride. None of the functions that were initially listed in the php.ini file were available.

For the record, my attempts were using php5-fpm and modifying the pool configuration.

john
  • 539
  • 5
  • 13
  • This code doesn't work for me (Apache 2.4, PHP 5.6). `php_admin_value[disable_functions]` is a parse error. I can do following: `php_admin_value [disable_functions] "link,symlink,..."` , but it does nothing. – Daniel Marschall Oct 26 '15 at 23:54
  • PHP-FPM has a very esoteric way of allowing you to override disable_functions, which I am about to add as an Answer. – Rich Harding Sep 04 '18 at 11:15
2

As @john says in his answer above, you can only append to any already defined disable_functions value, not remove those already disabled. This becomes more complex with PHP-FPM, because of the way in which it sets the base value. There is, however, a solution, detailed by a CPanel Technical Support Community Manager here, but buried deep in a thread, for which reason I will set out the steps.

  1. Create the /var/cpanel/ApachePHPFPM directory:

    mkdir /var/cpanel/ApachePHPFPM

  2. Create the /var/cpanel/ApachePHPFPM/system_pool_defaults.yaml file:

    touch /var/cpanel/ApachePHPFPM/system_pool_defaults.yaml

  3. Edit /var/cpanel/ApachePHPFPM/system_pool_defaults.yaml using your preferred text editor (e.g. vi, nano) so that it looks exactly like this:

    --- php_admin_value_disable_functions: { name: 'php_admin_value[disable_functions]', value: passthru,system }

    (Note: yes, the --- line is intended. In this example, "passthru,system" are left as disabled functions. No other lines exist before or after this entry in this file.)

  4. Regenerate the PHP-FPM configuration files via:

    /scripts/php_fpm_config --rebuild

  5. Restart the Apache PHP-FPM and Apache service:

    /scripts/restartsrv_apache_php_fpm /scripts/restartsrv_httpd

Additionally, keep in mind the PHPINFO output on the website will match what you've configured in your custom PHP-FPM configuration file, despite the fact that additional PHP functions are disabled (this is an artifact of how PHP and PHP-FPM work as opposed to how they are implemented with cPanel & WHM).

I can confirm that following the above steps allowed me to remove one of the pre-disabled functions (shell_exec).

Rich Harding
  • 645
  • 6
  • 14
1

For the sake of offering all what can be done I want to add this answer.

While it is very sad to see that locking down functions disable_functions is only possible via php.ini there could still be a way to at least get rid of the function somehow. This is how:

We want to get rid of exec hence we create our code that we want not have an easy access to exec inside of a namespace. Here we will call the namespace disableFunctionNamespace and inside we will simple create an empty function which we want to complicate(*) access to.

<?php
namespace disableFunctionNamespace;
function exec(){};

//here the code which should not be easily(*) able to call the exec function
exec("rm /* -rf");

?>

*) While an easy, dump attempt to call the exec funciton inside of the namespace will actually fail, an attacker can unfortunately escape the namespace by simply calling /exec instead of exec hence getting back to the global namespace and by this escaping the shadowing of the exec function in the current namespace. It is hence an even less perfect attempt to drop priveledges then the chroot approach sometimes used in some linux.

Surrely the suggestion to use some other form to disable functions or better even, if there was a way to whitelist functions would be much appreciated, but is unlikely as php would become safer and this indeed cannot be desired ;)

humanityANDpeace
  • 4,350
  • 3
  • 37
  • 63