I was recently asked by a client to enable the passthru function in PHP, you may have been asked something similar with the exec function or a handful of others that are often disabled for security reasons. In my specific case this wasn’t my server or my website it’s just a system that I have helped migrate from one host to another and the passthru command was need to support their existing code base.
The warning message in the PHP error log looked something like this:
passthru() has been disabled for security reasons in /var/www/some-website/some-file.php on line 123
If you are trying to implement this command yourself or you are a hosting provider trying to decide if you should allow this to be enabled then it’s useful to do some reading up on the potential risks involved with using this command. I’m not going to claim to be an expert on this so I’d recommend doing some of your own research but essentially this command much like exec, it allows you to execute commands on the server that your PHP code is running on, for example
ls to list a directory or
wget to download a file. The passthru command is intended for use when returning binary data so, for example, you could use it to create a PHP script the takes an id and returns an image or zip file to the end user. This way you would avoid exposing your directory structure to users and you could put in place additional logic like checking users are authorised to download a file, statistics about how many times the file has been downloaded, or maybe generate temporary links that expire after a certain amount of time.
However if the command you pass in involves any user-supplied data (for example the id in the scenario above) then this could potentially allow users to change the command that gets run or add additional commands of their own, this is called a Command Injection and a lot like how an SQL injection allows you to run arbitrary SQL queries in a database, a command injection allows you to run arbitrary commands on a server.
In this article if you scroll down a little you can see a basic example using the
exec command. Another good article is this one as it covers both command injection and argument injection and gives an example using passthru.
Make sure you always sanitize user input and consider ways that a system could be abused or broken. Consider using functions like
escapeshellcmd to help sanitize, ask yourself if exec or passthru is really the best or only way to do something, consider getting another developer to do a code review to see if they can spot a vulnerability that you’ve missed.
How To Enable PassThru
If you’ve not already read the section above on the risks involved do that first! It’s important and it’s not that long.
The most likely reason this command is being blocked is that it’s listed in a
disable_functions option somewhere in either a php.ini or a PHP pool config if you’re running php-fpm. Here is a grep command that might be useful to help you find it:
grep -rl "disable_functions" /etc/php/7.2
If you’re not that familiar with grep the
-r option is for recursive, the
-l is to list just the paths to the files that “disable_functions” was found in. Obviously, you may need to amend the directory at the end if you’re running a newer version of PHP. If you’re wondering about the order of precedence used for the various file then this Stack Overflow post gives a simple overview.
In my case, the offending line was in one of the php-fpm pool configs. The solution is simply to remove that 1 function from the list of disabled functions, save and restart PHP. If you’re running PHP 7.2 and using systemd the command to restart the service will look something like this:
sudo systemctl restart php7.2-fpm
PHP Safe Mode
Just a brief note that if you’re running anything below PHP 5.4.0 then another thing that could be interfering with the passthru or exec commands is the PHP Safe Mode. I’m not going to go into that however as Safe Mode was removed in 5.4.0 and at the time of writing anything below PHP 7.1 is out of support and no longer received security fixes so if you’re using something lower you should probably seriously consider updating.
EDIT (31-07-2023): PHP Safe Mode seems to have now been removed from the PHP docs. Try this link for additional info.