I am having an issue and I don't understand what is going on. I am basically using this PHP script to try and run a go binary :
<?php
shell_exec('/go/bin/x -arg -arg etc');
If I run this PHP file via command line it works. If I run it directly in browser (it's under www) it does not work. No errors whatsoever.
cli runs as root and apache as www-data. I have set the permissions to 0777 for /go/bin/x and I have also changed the owner / group to www-data. Still nothing.
What can cause this behavior ?
Also note that shell_exec works, but so far I have only ran other php files.
I do not know how I did not think about this before... The issue was that 1 of the input args contained a location to a text file and apache did not have the rights to read the file. The error was in /var/log/apache2/error.log
To Whom It May Concern.
I have same issue that I cannot run shell_exec/exec via website even they were run well in terminal.
See log:
[13-Jul-2020 19:57:23 UTC] PHP Warning: shell_exec() has been disabled for security reasons in /...test_script.php on line 3
Case 1: Check all php.ini where disable_function does not contain "shell_exec" or "exec"
$ sudo find / -name "php.ini"
$ sudo cat <path_to_php.ini> | grep disable_functions
// disable_functions = <<= This is OK
// disable_functions = "shell_exec, exec, system...." <<= They are disabled
Remove function that you want to use. Don't forget restart server.
Case 2: If disable_functions are all empty for all php.ini. Check your PHP-FPM on your hosting via Cpanel. Go to "MultiPHP Manager" from your Cpanel and check PHP-FPM status on your domain. Turn it off and you will be able to run shell_exec();
Related
Created .test.php file with one line of code:
<?php
var_dump(file_get_contents('https://checkip.amazonaws.com'));
?>
When I open .test.php from browser, it shows bool(false) but when I run it from command line, it shows my WAN IP as expected.
php -f .test.php
I am using CentOS 9, nginx 1.20.1, and PHP 8.1.3 (Although I've also tried RHEL8 and Apache)
I tried setting /etc/php-fpm.d/www.conf to use my userid and group to make sure it was not a permission problem.
phpinfo() shows allow_url_fopen is set to On and that curl 7.76.1 is enabled and that OpenSSL is enabled with version 3.0.1
I also tried with an http: URL
I also tried using curl() libraries in the .php file and those fail in the same manner.
Calling exec() from .php file works if it calls php -v or another .php file but not if it calls curl
Not sure what else to try, so I will probably nuke the whole server again.
UPDATE: Found this in /var/log/nginx/error.log
FastCGI sent in stderr: "PHP message: PHP Warning: file_get_contents(https://checkip.amazonaws.com): Failed to open stream: Permission denied
Now what?
There might be different settings of your PHP environment used in Command Line Interpreter/Interface CLI vs Common Gateway Interface CGI .
First compare what .ini files are loaded in both environment, ie.
for CLI run php -i
for CGI create a file phpinfo.php with only content <?php echo phpinfo(); and open it in the web browser.
Compare the results and see what modules are loaded and/or what .ini files are loaded.
Once I found the error log, I was able to find my answer. It was a Linux permission setting and running the following command fixed it:
setsebool -P httpd_can_network_connect on
I am running an Apache server on CentOS and need to run some bash scripts from PHP page. Running commands which do NOT need write or execute permission from PHP file works fine (for example shell_exec('ls /var/www/html/scripts/')), but I have problem running the commands that do need write or execute permission. For example this commands does nothing:
<?php
$output = shell_exec('/var/www/html/scripts/test.sh');
echo $output;
?>
I made apache user owner and granted necessary permissions to scripts directory:
drwxr-xr-x. 2 apache apache 21 Jun 3 09:54 scripts
and test.sh file as can be seen, but there was no lock.
-rwxr-xr-x. 1 apache apache 51 Jun 3 09:54 test.sh
I also tried to sudo the command in PHP file and added the line below to the end of Sudoers file, but nothing changed.
apache ALL=NOPASSWD: /var/www/html/scripts/test.sh
Also I checked PHP safe_mode which is off and there is no restriction in php.ini file:
disable_functions =
Your kind help would be highly appreciated.
NOTE:
I edited my bash script and added sudo like below:
#!/bin/bash
echo "Hi from test.sh";
sudo touch /var/www/html/scripts/file.log;
Now when I run the file as apache user using this command, it runs successfully:
su -s /bin/sh apache -c "/var/www/html/scripts/test.sh"
But through the php web page it only runs echo "Hi from test.sh"; line. When I check logs, there are lines below for running command above:
su: pam_unix(su:session): session opened for user apache by root(uid=0)
sudo: apache : TTY=unknown ; PWD=/var/www/html ; USER=root ; COMMAND=/bin/touch fromweb.log
su: pam_unix(su:session): session closed for user apache
And the generated log when running from php web page:
sudo: apache : TTY=unknown ; PWD=/var/www/html/scripts ; USER=root ; COMMAND=/bin/touch fromweb.log
Missing pam_unix(su:session) open and close.
I found what the issue was. It was because of Linux SELinux feature. This feature applies a least-privilege policy and denies any unnecessary command from running on Linux. The bash script is running successfully after disabling this feature. To do so, edit the file /etc/selinux/config and change SELINUX=enforcing to SELINUX=disabled and reboot the system. THIS IS NOT RECOMMENDED FOR SECURITY REASONS, however. You may check the link below to only create some exceptions rather than completely disabling SELinux.
https://wiki.centos.org/HowTos/SELinux
I am trying to run a command line file conversion using open office.
openoffice pdf filename.doc 2>&1
when i execute in command line as root it works fine and the file is converted. However when i pass the above command in a PHP file as apache user, it does not execute.
I tried all three PHP command line execution:
$command_output=system($command_line,$rtnval);
$command_output=exec($command_line,$rtnval);
$command_output=passthru($command_line,$rtnval);
Also,
echo print_r($rtnval);
echo print_r($command_output);
$rtnval returns 1 and $command_output 1. I am confused unable to know what is the linux (centos) response to above command passed. It is very frustration because unable to know what the system response when i try to execute the command.
I also included /etc/suders permission for apache to run the open office command.
apache ALL: (ALL) NOPASSWD: /path/to/openoffice
still the command is not execute in PHP as apache user.
What am i missing for PHP as apache user not to execute this command?
It could be that openoffice is not in PATH. Try to execute it with the full path.
To run your command as if you were the apache user, just try this in a shell:
# switch to superuser
sudo su -
# then switch to the apache user
su - www-data
You will find yourself in a quite restricted shell, from which it is usually not possible to start openoffice. Indeed, it requires a lot of environment, that would be unsafe to completely set up for apache anyway.
AFAIK, better create a dedicated user that is allowed to run your command (eg a regular "www-runner" user), then "su" to it from PHP. Other security measures include chroot'ing the dedidacted user, or using apparmor to limit what and where it is allowed to run. In any case, never let www-data run something as root by adding www-data to the sudoers: this is way too dangerous!
You can also have a look at libapache2-mod-suphp (a suid apache module to run php scripts with the owner permissions).It is easier to use than the dedicated suEXEC apache beast (http://httpd.apache.org/docs/2.0/suexec.html). The latter really is not for a quick fix ;)
It is possible that your php in apache runs in safe mode or what's it called, in which system() function and alike are disabled.
This answer, actually, assumes that what you call "running as apache user" is in fact running in apache environment, whatever it is.
I trying on my local CentOS 5.3 server, when I try to execute below line in my php code from apache webserver
exec("crontab -l", $output, $arg);
The $arg reply 127 (command not found code)
Then I changed below code
exec("/usr/bin/crontab -l", $output, $arg);
The $arg reply 126 (Permission problem code)
Here is my current permission of
/usr/bin/crontab -rwsr-sr-x 1 root root 311288 Mar 15 2007 /usr/bin/crontab.
And there is no /etc/cron.allow and /etc/cron.deny file.
I already turned off Safe_mode in php. Any suggestion to solve this problem?
////////////////////////////////////////////////////////////////////////////////
I note that my problem is related to selinux.
It is working, when I disable selinux
echo 0 > /selinux/enforce
But I don't want to disable selinux, is there any option in selinux to allow crontab from apache?
Add /usr/bin to your shell env path
Add crontab to the same group like of the webserver
Try in php exec("echo $PATH") to see the path variable. You can also look for unsetenv and temporarly disable it
You can look in the php error log for a detailed description of the error but as you said you are familiar with Linux I can't teach you about user right management. A note to the env variable and the path variable it's not always sure the env variable get exported when you run a program. This is maybe the case with your problem. It means either the os is broken or you have to attach the env variable manually to your program. A workaround can be to look where the shell is looking for programs and symlink the program. In your error log it seems that crontab is in the folder /usr/bin. Also this seems not to be a programming question. Ask at server.stackexchange why crontab isn't found. For example my env looks like this:
LC_PAPER=de_DE
LC_ADDRESS=de_DE
LC_MONETARY=de_DE
AF_PIDDIR=/tmp/af-piddir
UPNP_ROOT=upnpav://
SHELL=/bin/sh
TERM=xterm
DISABLE_GATEWAY=1
GTK2_RC_FILES=/etc/hildon/theme/gtk-2.0/gtkrc
TMPDIR=/var/tmp
MMC_SWAP_LOCATION=/media/mmc1
LC_NUMERIC=de_DE
MMC_MOUNTPOINT=/media/mmc1
OLDPWD=/root
HILDON_FM_OBEX_ROOT=obex://
LAUNCHWRAPPER_NICE_KILL=/etc/osso-af-init/nice-kill-launch-wrapper.sh
INTERNAL_MMC_MOUNTPOINT=/home/user/MyDocs
OSSO_VERSION=RX-51_2009SE_20.2010.36-2_PR_MR0
USER=root
LS_COLORS=no=00:fi=00:di=00;36:ln=00;35:pi=40;33:so=01;35:bd=40;32;00:cd=40;32;00:or=01;05;37;41:mi=01;05;37;41:ex=00;33:.cmd=00;32:.exe=00;32:.com=00;32:.btm=00;32:.bat=00;32:.sh=00;32:.csh=00;32:.tar=00;31:.tgz=00;31:.arj=00;31:.taz=00;31:.lzh=00;31:.zip=00;31:.z=00;31:.Z=00;31:.gz=00;31:.bz2=00;31:.bz=00;31:.tz=00;31:.rpm=00;31:.cpio=00;31:.jpg=00;35:.gif=00;35:.bmp=00;35:.xbm=00;35:.xpm=00;35:.png=00;35:.tif=00;35:
LC_TELEPHONE=de_DE
SESSION_BUS_PID_FILE=/tmp/dbus_session_bus.pid.user
OSSO_PRODUCT_HARDWARE=RX-51
STATESAVEDIR=/tmp/osso-appl-states
LAUNCHWRAPPER_NICE_TRYRESTART=/etc/osso-af-init/nice-launch-wrapper-tryrestart.sh
OSSO_PRODUCT_FULL_NAME=Nokia N900
OSSO_PRODUCT_RELEASE_FULL_NAME=Maemo 5
OSSO_PRODUCT_RELEASE_NAME=Maemo 5
MYDOCSDIR=/home/user/MyDocs
PATH=/usr/bin/gnu:/bin:/usr/bin:/usr/local/bin:/sbin:/usr/sbin:/usr/local/sbin
LC_MESSAGES=de_DE
OSSO_PRODUCT_SHORT_NAME=Nokia N900
SESSION_BUS_ADDRESS_FILE=/tmp/session_bus_address.user
LC_IDENTIFICATION=de_DE
PWD=/home/user/MyDocs
EDITOR=/usr/bin/nano -w -c
LANG=de_DE
ERR=0
LC_MEASUREMENT=de_DE
PS1=[\033[1;36m][[\033[0;36m]\u\h[\033[0;37m]:\w[\033[1;36m]][\033[m]$ [\033[0;37;00m]
ILLEGAL_FAT_CHARS=/:*?<>|
OSSO_PRODUCT_KEYBOARD=German
AF_DEFINES_SOURCED=1
SHLVL=1
HOME=/root
SDL_AUDIODRIVER=pulse
OSSO_SWAP=/home/user/MyDocs
OSSO_PRODUCT_RELEASE_VERSION=20.2010.36-2
LS_OPTIONS=--color
LAUNCHWRAPPER_TRYRESTART=/etc/osso-af-init/launch-wrapper-tryrestart.sh
OSSO_PRODUCT_NAME=N900
AF_INIT_DIR=/etc/osso-af-init
MMC_DEVICE_FILE=/dev/mmcblk0p1
LOGNAME=root
DBUS_SESSION_BUS_ADDRESS=unix:abstract=/tmp/dbus-eCbOI2qrVP,guid=cd1dea104334a338a9007b9700000014
LAUNCHWRAPPER=/etc/osso-af-init/launch-wrapper.sh
OSSO_PRODUCT_WLAN_CHANNEL=fcc/us
MAX_FILENAME_LENGTH=255
DISPLAY=:0.0
LAUNCHWRAPPER_NICE=/etc/osso-af-init/nice-launch-wrapper.sh
LC_TIME=de_DE
INTERNAL_MMC_SWAP_LOCATION=/home/user/MyDocs
LC_NAME=de_DE
OSSO_PRODUCT_REGION=Germany
_=/usr/bin/gnu/env
Just type env in the prompt.
I'm running php as a shell script.
(I am not sure if "shell script" is correct. The file starts with #!/usr/bin/php.)
This works great. But the MongoDB class doesn't get loaded as the correct php.ini file (having extension=mongo.so) is not used.
How do I make it use that php.ini file?
I already tried #!/usr/bin/php -c /usr/local/lib/php.ini
But I still get the same error - Fatal error: Class 'Mongo' not found
What can be done?
Try putting php.ini in the same folder as the php binary. It seems to look there first.
I know this because I used a very powerful and useful command-line program called strace to show me what's really going on behind my back
$ strace -o strace.log php --version
$ grep php.ini strace.log
Strace digs out kernel (system) calls that your program makes and dumps the output into the file specified after -o
It's easy to use grep to search for occurrences of php.ini in this log. It's pretty obvious looking at the following typical response to see what is going on.
open("/usr/bin/php.ini", O_RDONLY) = -1 ENOENT (No such file or directory)
open("/etc/php.ini", O_RDONLY) = 3
lstat("/etc/php.ini", {st_mode=S_IFREG|0644, st_size=69105, ...}) = 0
Edit .bashrc located at your home directory and add this line:
alias php='php -c /path-to-custom/php.ini'
In this particular situation. I would
Check to see if the Mongo module is loaded (using extension_loaded() or class_exists())
If not loaded, try to load the Mongo module using dl()
If loading fails, display an error message so the admin can take care of it (STDERR or trigger_error()
Most distributions already ship different versions of php.ini for Web Servers and CLI. Are there other reasons to add another php.ini configuration for script XYZ (in addition to normal configuration)?
I came across this, because I had the same problem. Problem is there is more than one php.ini file used.
The one used by Apache is located in
/etc/php5/apache2/php.ini
This is the one that is modified to run MongoDB with extension=mongo.so.
However, when running a cron job, or from the terminal, it loads a different ini file. You can find this by using the line
grep php.ini strace.log
It is mentioned by thomas-peter.
The path where it displays '=3' is the php.ini file loaded when running the engine from the terminal, this ini file will need "extension=mongo.so" placed in it as well.
The other option is to use a small sh wrapper, something like this below in a myapp.sh file. Don’t forget to chmod +x on the script to run it.
#!/usr/bin/env sh
SOMEVAR='Yea Baby!'
export SOMEVAR
php -c /path/to/my/custom/php.ini /path/to/my/old_script.php
With the added bonus of being able to set or override environment variables pre-run.
This is a bit of a gotcha with PHP.
php -c /path/to/my/custom/php.ini works from the command line.
But try it in a script like this #!/usr/local/bin/php -c /path/to/my/custom/php.ini and your custom php won't load.
The Solution
Get rid of the space between -c and your path:
#!/usr/local/bin/php -c/path/to/my/custom/php.ini