Executing a shell script from a PHP script - php

I want to execute a Bash script present on the system from a PHP script. I have two scripts present on the system. One of them is a PHP script called client.php present at /var/www/html and the other is a Bash script called testscript present at /home/testuser.
My client.php script looks like
<?php
$message=shell_exec("/home/testuser/testscript 2>&1");
print_r($message);
?>
My testscript looks like
#!/bin/bash
echo "Testscript run succesful"
When i do the following on terminal
php client.php
I get the following output on terminal
Testscript run successful
But when i open the page at
http://serverdomain/client.php
I get the following output
sh: /home/testuser/testscript: Permission denied
I get this error even after I did chmod +x testscript.
How do I get it to work from the browser? Please help.

I would have a directory somewhere called scripts under the WWW folder so that it's not reachable from the web but is reachable by PHP.
e.g. /var/www/scripts/testscript
Make sure the user/group for your testscript is the same as your webfiles. For instance if your client.php is owned by apache:apache, change the bash script to the same user/group using chown. You can find out what your client.php and web files are owned by doing ls -al.
Then run
<?php
$message=shell_exec("/var/www/scripts/testscript 2>&1");
print_r($message);
?>
EDIT:
If you really want to run a file as root from a webserver you can try this binary wrapper below. Check out this solution for the same thing you want to do.
Execute root commands via PHP

Without really knowing the complexity of the setup, I like the sudo route.
First, you must configure sudo to permit your webserver to sudo run the given command as root. Then, you need to have the script that the webserver shell_exec's(testscript) run the command with sudo.
For A Debian box with Apache and sudo:
Configure sudo:
As root, run the following to edit a new/dedicated configuration file for sudo:
visudo -f /etc/sudoers.d/Webserver
(or whatever you want to call your file in /etc/sudoers.d/)
Add the following to the file:
www-data ALL = (root) NOPASSWD: <executable_file_path>
where <executable_file_path> is the command that you need to be able to run as root with the full path in its name(say /bin/chown for the chown executable). If the executable will be run with the same arguments every time, you can add its arguments right after the executable file's name to further restrict its use.
For example, say we always want to copy the same file in the /root/ directory, we would write the following:
www-data ALL = (root) NOPASSWD: /bin/cp /root/test1 /root/test2
Modify the script(testscript):
Edit your script such that sudo appears before the command that requires root privileges(say sudo /bin/chown ... or sudo /bin/cp /root/test1 /root/test2). Make sure that the arguments specified in the sudo configuration file exactly match the arguments used with the executable in this file.
So, for our example above, we would have the following in the script:
sudo /bin/cp /root/test1 /root/test2
If you are still getting permission denied, the script file and it's parent directories' permissions may not allow the webserver to execute the script itself.
Thus, you need to move the script to a more appropriate directory and/or change the script and parent directory's permissions to allow execution by www-data(user or group), which is beyond the scope of this tutorial.
Keep in mind:
When configuring sudo, the objective is to permit the command in it's most restricted form. For example, instead of permitting the general use of the cp command, you only allow the cp command if the arguments are, say, /root/test1 /root/test2. This means that cp's arguments(and cp's functionality cannot be altered).

I was struggling with this exact issue for three days. I had set permissions on the script to 755. I had been calling my script as follows.
<?php
$outcome = shell_exec('/tmp/clearUp.sh');
echo $outcome;
?>
My script was as follows.
#!bin/bash
find . -maxdepth 1 -name "search*.csv" -mmin +0 -exec rm {} \;
I was getting no output or feedback. The change I made to get the script to run was to add a cd to tmp inside the script:
#!bin/bash
cd /tmp;
find . -maxdepth 1 -name "search*.csv" -mmin +0 -exec rm {} \;
This was more by luck than judgement but it is now working perfectly. I hope this helps.

It's a simple problem. When you are running from terminal, you are running the php file from terminal as a privileged user. When you go to the php from your web browser, the php script is being run as the web server user which does not have permissions to execute files in your home directory. In Ubuntu, the www-data user is the apache web server user. If you're on ubuntu you would have to do the following:
chown yourusername:www-data /home/testuser/testscript
chmod g+x /home/testuser/testscript
what the above does is transfers user ownership of the file to you, and gives the webserver group ownership of it. the next command gives the group executable permission to the file. Now the next time you go ahead and do it from the browser, it should work.

Related

www-data user not able to write to fifo, chmodded 777

I wrote a little PHP script that I'd like to call from Apache. I'm intending to use this to control pianobar.
If I execute the script directly from a root terminal, it works just fine, but if I try to run the script through the web server, nothing.
The fifo I created is at /home/dave/.config/pianobar/piano and the relevant lines in the PHP script look like this...
<?php
system("echo -n 'p' > /home/dave/.config/pianobar/piano"); //'p' pauses pianobar.
echo system('whoami');
?>
If I execute this script in a browser through Apache, it echoes 'www-data www-data' which tells me that safe mode is disabled and the system() command is working, but pianobar keeps playing. If I run this from a root terminal, it echoes back 'root' and pianobar pauses. If I execute this from a terminal under my own username, it echoes back 'dave' and pianobar still pauses.
The fifo I created /home/dave/.config/pianobar/piano was chmodded to 777. What gives? Is this a permissions issue somehow? Is PHP not allowing me to do anything useful with the system() command?
Check folder permissions:
stat --format '%a' /home/dave/.config/pianobar/piano
Set folder permissions for all files inside of folder:
sudo chmod -R 755 /home/dave/.config/pianobar/piano
Try, should work.

PHP executing external commands - how to when username and password required

Okay so I want to change the file mode of a directory to 777 so I use the line
exec('chmod -R 777' . $dir);
where $dir is the directory path of the directory I wanna change
it doesn't seem to work but I don't get an error for it, also if the user I was executing the script from was a sudo user so I have to enter the password after I enter the command, how would I do this? Would it be something like exec('chmod -R 777' . $dir\n 'password'); ?
Information I get from this site
Execute system commands via PHP
Many a times we need to execute system commands on a Linux system – to delete a directory, or restart a service. However, since Apache does not run with root privileges, it is nearly impossible to use PHP’s exec(), system() or passthru() functions to achieve that.
The solution to this is very simple, specially on Ubuntu. The Apache’s user www-data need to be granted privileges to execute certain applications using sudo.
1.Run the command sudo visudo
2.At the end of the file, add the following
www-data ALL=NOPASSWD: /sbin/iptables, /usr/bin/du
This is assuming that you wish to run iptables and du using super user (root) privileges. However, if you wish to run every application using super user privileges, then add the following instead of what’s above
www-data ALL=NOPASSWD: ALL
3.That’s it, now use exec() in the following manner inside your .php script
exec ("sudo iptables -P FORWARD ACCEPT");

Executing bash script as root from a php script [duplicate]

I want to execute a Bash script present on the system from a PHP script. I have two scripts present on the system. One of them is a PHP script called client.php present at /var/www/html and the other is a Bash script called testscript present at /home/testuser.
My client.php script looks like
<?php
$message=shell_exec("/home/testuser/testscript 2>&1");
print_r($message);
?>
My testscript looks like
#!/bin/bash
echo "Testscript run succesful"
When i do the following on terminal
php client.php
I get the following output on terminal
Testscript run successful
But when i open the page at
http://serverdomain/client.php
I get the following output
sh: /home/testuser/testscript: Permission denied
I get this error even after I did chmod +x testscript.
How do I get it to work from the browser? Please help.
I would have a directory somewhere called scripts under the WWW folder so that it's not reachable from the web but is reachable by PHP.
e.g. /var/www/scripts/testscript
Make sure the user/group for your testscript is the same as your webfiles. For instance if your client.php is owned by apache:apache, change the bash script to the same user/group using chown. You can find out what your client.php and web files are owned by doing ls -al.
Then run
<?php
$message=shell_exec("/var/www/scripts/testscript 2>&1");
print_r($message);
?>
EDIT:
If you really want to run a file as root from a webserver you can try this binary wrapper below. Check out this solution for the same thing you want to do.
Execute root commands via PHP
Without really knowing the complexity of the setup, I like the sudo route.
First, you must configure sudo to permit your webserver to sudo run the given command as root. Then, you need to have the script that the webserver shell_exec's(testscript) run the command with sudo.
For A Debian box with Apache and sudo:
Configure sudo:
As root, run the following to edit a new/dedicated configuration file for sudo:
visudo -f /etc/sudoers.d/Webserver
(or whatever you want to call your file in /etc/sudoers.d/)
Add the following to the file:
www-data ALL = (root) NOPASSWD: <executable_file_path>
where <executable_file_path> is the command that you need to be able to run as root with the full path in its name(say /bin/chown for the chown executable). If the executable will be run with the same arguments every time, you can add its arguments right after the executable file's name to further restrict its use.
For example, say we always want to copy the same file in the /root/ directory, we would write the following:
www-data ALL = (root) NOPASSWD: /bin/cp /root/test1 /root/test2
Modify the script(testscript):
Edit your script such that sudo appears before the command that requires root privileges(say sudo /bin/chown ... or sudo /bin/cp /root/test1 /root/test2). Make sure that the arguments specified in the sudo configuration file exactly match the arguments used with the executable in this file.
So, for our example above, we would have the following in the script:
sudo /bin/cp /root/test1 /root/test2
If you are still getting permission denied, the script file and it's parent directories' permissions may not allow the webserver to execute the script itself.
Thus, you need to move the script to a more appropriate directory and/or change the script and parent directory's permissions to allow execution by www-data(user or group), which is beyond the scope of this tutorial.
Keep in mind:
When configuring sudo, the objective is to permit the command in it's most restricted form. For example, instead of permitting the general use of the cp command, you only allow the cp command if the arguments are, say, /root/test1 /root/test2. This means that cp's arguments(and cp's functionality cannot be altered).
I was struggling with this exact issue for three days. I had set permissions on the script to 755. I had been calling my script as follows.
<?php
$outcome = shell_exec('/tmp/clearUp.sh');
echo $outcome;
?>
My script was as follows.
#!bin/bash
find . -maxdepth 1 -name "search*.csv" -mmin +0 -exec rm {} \;
I was getting no output or feedback. The change I made to get the script to run was to add a cd to tmp inside the script:
#!bin/bash
cd /tmp;
find . -maxdepth 1 -name "search*.csv" -mmin +0 -exec rm {} \;
This was more by luck than judgement but it is now working perfectly. I hope this helps.
It's a simple problem. When you are running from terminal, you are running the php file from terminal as a privileged user. When you go to the php from your web browser, the php script is being run as the web server user which does not have permissions to execute files in your home directory. In Ubuntu, the www-data user is the apache web server user. If you're on ubuntu you would have to do the following:
chown yourusername:www-data /home/testuser/testscript
chmod g+x /home/testuser/testscript
what the above does is transfers user ownership of the file to you, and gives the webserver group ownership of it. the next command gives the group executable permission to the file. Now the next time you go ahead and do it from the browser, it should work.

Accessing /var/log files from php

I want to use PHP to show some syslog info on a web page to remote monitor my home linux box.
I.e. some stuff filtered with grep out of /var/log/daemon.log
<?php
$output = `grep ddclient /var/log/daemon.log`;
echo "<pre>$output</pre>";
?>
Now the file /var/log/daemon.log is owned by root and the PHP user (www-data) has no access.
So obviously the above returns empty.
What's the solution?
Thanks,
Gert
This is a variant of Puggan Se's setuid solution, but a bit better IMHO.
Create a grep_ddclient.sh shell script, containing:
#!/bin/sh
grep ddclient /var/log/daemon.log
Then add the following to /etc/sudoers:
apache ALL=NOPASSWD: /path/to/grep_ddclient.sh
Then run sudo /path/to/grep_ddclient.sh from PHP
Alt 1:
change read access of the file /var/log/daemon.log so apache can read it.
Alt 2:
put grep ddclient /var/log/daemon.log in a shell file, and then activate the SETUID flag on it, and give apache the right to execute it
chown root:apache grep_ddclient.sh
chmod 550 grep_ddclient.sh
chmod +s grep_ddclient.sh
and then run grep_ddclient.sh from php

How to execute a shell script in PHP?

I have a script in /var/www/myscript.sh which creates folders and runs the command svn update for my projects. I need to execute this script by calling it in a PHP file in the browser (i.e. Localhost/test.php). I tried using functions shell_exec() and exec() but those did not work. I ran my shell script in terminal with su www-data && ./myscript.sh and it worked. What else am I missing?
<?php
$output = shell_exec("./myscript.sh");
?>
Update 5/4/2011:
I added www-data ALL=(ALL) NOPASSWD:ALL to /etc/sudoers and it works, but this is very insecure. Is there another way to do this?
Several possibilities:
You have safe mode enabled. That way, only exec() is working, and then only on executables in safe_mode_exec_dir
exec and shell_exec are disabled in php.ini
The path to the executable is wrong. If the script is in the same directory as the php file, try exec(dirname(__FILE__) . '/myscript.sh');
You might have disabled the exec privileges, most of the LAMP packages have those disabled. Check your php.ini for this line:
disable_functions = exec
And remove the exec, shell_exec entries if there are there.
Good Luck!
Residuum did provide a correct answer to how you should get shell exec to find your script, but in regards to security, there are a couple of points.
I would imagine you don't want your shell script to be in your web root, as it would be visible to anyone with web access to your server.
I would recommend moving the shell script to outside of the webroot
<?php
$tempFolder = '/tmp';
$webRootFolder = '/var/www';
$scriptName = 'myscript.sh';
$moveCommand = "mv $webRootFolder/$scriptName $tempFolder/$scriptName";
$output = shell_exec($moveCommand);
?>
In regards to the:
i added www-data ALL=(ALL) NOPASSWD:ALL to /etc/sudoers works
You can modify this to only cover the specific commands in your script which require sudo. Otherwise, if none of the commands in your sh script require sudo to execute, you don't need to do this at all anyway.
Try running the script as the apache user (use the su command to switch to the apache user) and if you are not prompted for sudo or given permission denied, etc, it'll be fine.
ie:
sudo su apache (or www-data)
cd /var/www
sh ./myscript
Also... what brought me here was that I wanted to run a multi line shell script using commands that are dynamically generated. I wanted all of my commands to run in the same shell, which won't happen using multiple calls to shell_exec(). The answer to that one is to do it like Jenkins - create your dynamically generated multi line of commands, put it in a variable, save it to a file in a temp folder, execute that file (using shell_exec in() php as Jenkins is Java), then do whatever you want with the output, and delete the temp file
... voila
If you are having a small script that you need to run (I simply needed to copy a file), I found it much easier to call the commands on the PHP script by calling
exec("sudo cp /tmp/testfile1 /var/www/html/testfile2");
and enabling such transaction by editing (or rather adding) a permitting line to the sudoers by first calling sudo visudo and adding the following line to the very end of it
www-data ALL=(ALL) NOPASSWD:/bin/cp /tmp/testfile1 /var/www/html/testfile2
All I wanted to do was to copy a file and I have been having problems with doing so because of the root password problem, and as you mentioned I did NOT want to expose the system to have no password for all root transactions.

Categories