|Kyberdigi Projects Execdir
|About Installation Configuration Download Bugs
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.
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:
php_admin_value exec_dir /usr/local/php/bin/virtual1.tld
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
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 you want to disable exec_dir in a directory for any reason, just set the value of the directive to none:
php_admin_value exec_dir /usr/local/php
php_admin_value exec_dir none
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 email@example.com.
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.
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.
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.
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.
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.
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.
The patch has not been tested on Windows platform yet. If you test it and it will work, let me know.