en cz  
2016-11-11

Patch for PHP 5.6.28 released.

2016-11-04

Patch for PHP 5.6.27 released.

2016-09-19

Patch for PHP 5.6.26 released.

2016-09-06

Patches for PHP 5.6.23, 5.6.24, 5.6.25, 5.5.37 and 5.5.38 released.

2016-05-31

Patches for PHP 7.0.7, 5.6.22 and 5.5.36 released.

2016-04-29

Patches for PHP 7.0.6, 5.6.21 and 5.5.35 released.

2016-04-01

Patches for PHP 7.0.5, 5.6.20 and 5.5.34 released.

2016-03-11

Patches for PHP 7.0.4, 5.6.19 and 5.5.33 released.

RSS
Progamming language PHP allows one to limit executing of external commands via configuration directive safe_mode_exec_dir. This directive should contain full path to a directory conatining programs which PHP script can run. If the script tries to execute a command not located in this directory, the command is not executed. This configuration directive is active only if safe mode is enabled, which means more and sometimes unwanted restrictions to users. PHP has no known possibility to limit executing of external commands with disabled safe mode. Teherefore, here is a patch adding special directive exec_dir straightly into PHP. This directive is very similar to safe_mode_exec_dir, but safe mode has not to be enabled.

This patch limits or corrects the behavior of these functions:

  • exec()
  • passthru()
  • proc_open()
  • shell_exec()
  • system()
  • popen()
  • is_executable()

The patch was created for purposes of limit execution of external commands of users on a multidomain apache server, first for PHP version 4.2.1. The patch was sent to PHP developers so it could be a part of PHP, but no one of PHP developers was interested in. On the other side, some PHP users wanted this patch, therefore this site was created.

Note:
The message to the PHP-DEV mailing list has been sent on 2002-06-21.

This patch modifies PHP source, so first of all you need the PHP source, download it from from official PHP site. After unpacking the archive, step into the directory witch PHP unpacked and apply the patch:

$ cd /path/to/directory/with/php-x.y.z
$ zcat /patch/to/file/php-exec-dir.x.y.z.patch.gz | patch -p1

If everything went OK, you should see output similar to this one:

patching file ext/standard/exec.c
patching file ext/standard/file.c
patching file ext/standard/filestat.c
patching file ext/standard/proc_open.c
patching file main/main.c
patching file main/php_globals.h
patching file php.ini-development
patching file php.ini-production

Now you have to compile and install the PHP as usual.

Note:
Patch is being compressed with gzip, so you have to use zcat to decompress it for the patch program or gunzip to decompress the patch as such.

All you have to do is set the directive exec_dir. You can do this in php.ini or in configuration files of http server Apache. Beacause of some security reasons, this variable cannot be changed while running PHP script. The directive should contain full path to an existing directory which contains files or symlinks to files which can be executed.

For example, let's imagine a server with http Apache server, which serves 2 virtuals: virtual1.tld and virtual2.tld, each of these being maintained by other person. Maintainer of virtual1.tld wants to execute cp, rm and mv, maintainer of virtual2.tld wants to execute mysqldump. The most clean solution now is to create one directory for virtual1.tld, i.e. /usr/local/php/bin/virtual1.tld and place binaries cp, rm and mv into it (or create symlinks to them). Similary we should create /usr/local/php/bin/virtual2.tld with mysqldump in it. Of cource it is better to create symlinks than to copy raw files, because of upgrades. Now we have to configure Apache:

<VirtualHost virtual1.tld>
  php_admin_value exec_dir /usr/local/php/bin/virtual1.tld
</VirtualHost>

<VirtualHost virtual2.tld>
  php_admin_value exec_dir /usr/local/php/bin/virtual2.tld
</VirtualHost>

A bit more simple is to create one directory for whole server containing trusted commands. In our example we can create directory /usr/local/php and place (or create symlinks) cp, mv, rm and mysqldump in it. Now it is enough to edit the php.ini file, where should be this line:

exec_dir = /usr/local/php

Note:
After editing php.ini or Apache configuration files, the Apache server has to be restarted.

Now we have to describe how the executing works. The name of the command to be executed will be modified, first it will be shorted: only characters behind last occurence of '/' will rest. Before this new command name, the contents of exec_dir will be placed. For example, if we call /bin/cp and directive exec_dir conatins /usr/local/php, the command /bin/cp will be modified to cp and then to /usr/local/bin/cp. This command will be executed.

PHP behavior is influenced by these settings:

  • if the exec_dir directive is not set or is set to an empty string, functions exec(), popen() etc. are running without any restrictions
  • if safe mode is enabled and safe_mode_exec_dir is set, exec_dir is ignored
  • if exec_dir is set, the called command cannot contain strings ".." and ";", similar functionality offers safe_mode_exec_dir

If you want to disable exec_dir in a directory for any reason, just set the value of the directive to none:

<VirtualHost virtual.tld>
  php_admin_value exec_dir /usr/local/php
  <Location /free>
    php_admin_value exec_dir none
  </Location>
</VirtualHost>

Select PHP version:

PHP version:
Date:
Size:
MD5:
Direct link:

There are no known bugs at this moment. If you have exec_dir set to some directory and you will execute command out of it, please let me know at mccohy@kyberdigi.cz.

2014-03-10

Martijn Grendelman requested fix of bug reported on 2012-08-22, mainly because Debain Weezy is shipped with PHP 5.4.4. Patches have been fixed, you can now download valid files.

2012-08-22

Manuel Mausz has discovered a bug in versions 5.4.0 - 5.4.4 inclusive. Bad placing of a new block into original code made some functions (file_exists, is_executable etc.) to return false unless these tested files were placed in directory defined in the exec_dir directive. Thanks for reporting and an attached patch. Please upgrade to version 5.4.5 or higher.

2011-01-03

Antihack000 informed, that calling of PHP function proc_open() completely ignores any value set in variable exec_dir. This bug was fixed in patches for versions 5.2.15 and higher. If you are using lower version, please upgrade.

2008-03-16

Possible memory leak has been found by Manuel Mausz. He also sent a patch for exec_dir patch solving the issue (thanks!). All versions of the exec_dir patch bellow 5.2.11 include the leak, so please upgrade to 5.2.11, patch for this version is secure.

2004-08-16

A minimalistic bug about disabling exec_dir has been discovered by myself. If you want to disable the exec_dir in (i.e.) httpd.conf, you have to add this line somewhere:

php_admin_value exec_dir none

Although you set it so, it does not disable the usability of exec_dir, but it tries to run binaries as if they were in the root directory of the filesystem (/ls, /df etc.). If you are in trouble with this, please download new patch for your version of PHP. All patches listed in section download are correct ones, so check the MD5 of the patch you have to those in the list. Vulnerable versions: 4.3.2 - 4.3.8 (inclusive), 5.0.0 and 5.0.1. This is not a really dramatical bug you should really worry about.

2004-06-24

VeNoMouS reported that you can execute commands out of specified directories if you prepend a ';', '|', '&' or may other ugly character to the beginning of the command and try to execute it with the backtick operator. In original safe_mode_exec_dir the backtick operator is turned off, in this patch it is not. Therefore, all the patches listed here were updated with a simple fix that escapes these and other characters the same way as other commands (as exec() or popen()) do. You are strongly encouraged to download new patch for your version of PHP. The patches listed in section download are correct ones, so check the MD5 of the patch you have to those in the list. All version from 4.3.2 to 4.3.7 (inclusive) were vulnerable.

Note:
The patch has not been tested on Windows platform yet. If you test it and it will work, let me know.