I have a CentOS 5.7 linux server and use php5.3.x.
On a pfSense system, you can restart services-that required root permissions using a php web page.
I'm trying to do something similar, I have written some php code to execute shell commands. For example, to restart the sshd service:
<?php
exec('/sbin/service sshd restart');
?>
and I tried to execute that command via exec function, but it needs root permission, but we have a apache user authority.
I have come across a few solutions:
"run apache with root user"
really unsafe. I do not want to do that.
"apache ALL=NOPASSWD:/sbin/service to /etc/sudoers"
I tried but and still have a problem.
Any other solutions?
Thanks for answers.
now.. it's interesting. i tried #refp post and it worked my local ubuntu server. But when i tried same at my cenOS vps server. It's not working.and that is apache's error log "rm: cannot remove `/var/lock/subsys/vsftpd': Permission denied"
Read this whole post before trying it out, there are choices to be made.
Solution using a binary wrapper (with suid bit)
1) Create a script (preferrably .sh) that contains what you want to be ran as root.
# cat > php_shell.sh <<CONTENT
#!/bin/sh
/sbin/service sshd restart
CONTENT
2) This file should be owned by root, and since it will later run with root permissions make sure that only root has permission to write to the file.
# chown root php_shell.sh
# chmod u=rwx,go=xr php_shell.sh
3) To run the script as root no matter what user that executes it, we will need a binary wrapper. Create one that will execute our php_shell.sh.
# cat > wrapper.c <<CONTENT
#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>
int
main (int argc, char *argv[])
{
setuid (0);
/* WARNING: Only use an absolute path to the script to execute,
* a malicious user might fool the binary and execute
* arbitary commands if not.
* */
system ("/bin/sh /path/to/php_shell.sh");
return 0;
}
CONTENT
4) Compile and set proper permissions, including the suid bit (saying that it should run with root privileges):
# gcc wrapper.c -o php_root
# chown root php_root
# chmod u=rwx,go=xr,+s php_root
php_root will now run with root permissions, and execute the commands specified in php_shell.sh.
If you don't need to the option to easily change what commands that will be executed I'd recommend you to write the commands directly in wrapper.c under step 4. Then you don't need to have a binary executing a external script executing the commands in question.
In wrapper.c, use system ("your shell command here"); to specify what commands you'd like to execute.
I would not have PHP execute any sudo commands. To me that sounds like asking for trouble. Instead I would create two separate systems.
The first system, in PHP (the web tier), would handle user requests. When a request is made that needs a sudo command I would place this request in some queue. This could be a database of some sort or middle-ware such as ZeroMQ.
The second system (the business tier) would read or receive messages from this queue and would have the ability to execute sudo commands but won't be in the scope of your web-server process.
I know this is a bit vague and it can be solved in different ways with various technologies but I think this is the best and safest way to go.
Allow the www-data user to run to run program1 and program2 with no password:
sudo visudo
Add to the contents of the sudoers file:
User_Alias WWW_USER = www-data
Cmnd_Alias WWW_COMMANDS = /sbin/program1, /sbin/program2
WWW_USER ALL = (ALL) NOPASSWD: WWW_COMMANDS
Save.
from https://askubuntu.com/questions/76920/call-a-shell-script-from-php-run-as-root
Solution using a binary wrapper (with suid bit)
Some modification of Filip Roséen - refp post.
To execute any command modified wrapper.c
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>
#include <string.h>
int main (int argc, char **argv)
{
setuid (0);
char cmd[100] = "";
int i;
char *p;
for(i=0; i < argc; i++) {
if(i != 0){
strcat(cmd, *(argv+i));
strcat(cmd, " ");
}
}
system (cmd);
return 0;
}
Compile and set proper permissions;
gcc wrapper.c -o php_root # php_root can be any name.
chown root php_root
chmod u=rwx,go=xr,+s php_root
Now call from PHP. Execute any command.
shell_exec('./php_root '.$cmd);//execute from wrapper
I recently published a project that allows PHP to obtain and interact with a real Bash shell, it will easily give you a shell logged in as root. Then you can just execute the individual bash commands rather than bundling then in a script. That way you can also handle the return. Get it here: https://github.com/merlinthemagic/MTS
After downloading you would simply use the following code:
$shell = \MTS\Factories::getDevices()->getLocalHost()->getShell('bash', true);
$return1 = $shell->exeCmd('service sshd restart');
echo $return1;
//On CentOS 7 output would be like:
//Redirecting to /bin/systemctl restart sshd.service
//On CentOS 6 and lower output would be like:
//Stopping sshd: [ OK ]
//Starting sshd: [ OK ]
setenforce 0
Write this command in the terminal this command will disable SELinux.
this isn't a good practice.
Related
I have a php file which is called by a website:
example: serial_tx.php?v=W100
Within the php I write a log file where I can see which string v I received (W100 in this case).
The webserver is hosted on a Raspberry Pi and should send this data to the uart.
The files locations:
/SCRIPTS/serial_tx.php
/SCRIPTS/c/jmsend/serial_tx // the executable, compiled from a C script
If I am in the root of the webserver and, from the console of my Pi, I run
sudo /var/www/html/SCRIPTS/c/jmsend/serial_tx W100
I get the command sent correctly.
With the php file I tried with system, shell_exec and exec without success.
shell_exec("sudo /var/www/html/SCRIPTS/c/jmsend/serial_tx ".$ric);
$ric is the received command.
I tried with different path settings too (starting from Pi root or webserver root).
All the files have a 777 as permissions.
Something like this in /etc/sudoers should work to allow your web server user to run that particular command without issue:
Cmnd_Alias SERIAL = /var/www/html/SCRIPTS/c/jmsend/serial_tx *
www-data ALL=(ALL) NOPASSWD: SERIAL
Note that you must escape user input before using it:
$ric = escapeshellarg($_GET["v"]);
shell_exec("sudo /var/www/html/SCRIPTS/c/jmsend/serial_tx $ric");
You should also be aware of the differences between exec() and shell_exec(), specifically that you can't check for a failure using shell_exec().
$ric = escapeshellarg($_GET["v"]);
exec("sudo /var/www/html/SCRIPTS/c/jmsend/serial_tx $ric", $output, $return);
if ($return !== 0) {
// let the user know something didn't work
}
This assumes, of course, that your executable is written to return appropriate error codes.
I building one PHP application where I create command line functionality for Linux debian Jessie. All works fne but I need to be able use some commands like root user.
Is there a way to use shell_exec() or similar command to access like root user via PHP?
Idea of this command line is to people who have access to that server can handle with it over internet from any place or device.
Here is image of console:
Executing commands as root via PHP will leave yourself wide open to all sorts of malicious hackery.
Have a look at the "sudo" documentation.
You should be able to set up all the commands you need as "sudo"able scripts. It is much better to write specific scripts with limited functions than to expose the underlying priviledged command.
As in:
exec ('sudo getCurrentUser.sh')
First, you need to add the user that PHP is using to run (most of the time it is www-data) to the sudo group if it is not already assigned.
Then, in your php file:
use sudo -S, so you can pass the password via echo
$exec = "echo your_passwd | /usr/bin/sudo -S your command";
exec($exec,$out,$rcode);
if you have trouble with the paths - use
"bash -lc 'echo your_passwd | /usr/bin/sudo -S your command'"
so you get a new bash that acts like a login shell and has the paths set
Edit your sudoers file
sudo vi /etc/sudoers
Put this line
www-data ALL=(ALL) NOPASSWD: ALL
www-data is the php default user in linux ( replace if necessary )
Use
$output = shell_exec('sudo XXXX');
I have a C program that makes a system call (centOS 6.0) to encrypt a file, my code is:
#include <stdlib.h>
int main () {
system ("gpg -c --batch --passphrase mypass file.txt");
return 0;
}
The executable object is called encrypt_file
When I run ./encrypt_file directly through CLI it runs perfectly I obtain my file.txt.gpg, but when I try to execute it via browser I get no response.
Code in php:
shell_exec("./encrypt_file");
The reason I chose to make a c program is that I need the passphrase to be in the code but not visible, when I delete the .c file that contains the passphrase all I have left is my .exe and no visible passphrase.
I already changed permissions to apache user by issuing the following:
chown apache.apache /var/www/html/
And added the next line in /etc/sudoers:
apache ALL=(ALL) NOPASSWD:ALL
NOTE: The only command I have issues is gpg, I can make a system call with any other command that I needed to use, I can even run python scripts, and other C programs that doesn't contain anything related to gpg.
I hope a fast reply! I need to use a lot this encrypt_file!
Checking the error_log in /var/log/httpd/error_log I saw this line:
gpg: Fatal: can't create directory `/var/www/.gnupg': Permission denied
Then I found a solution at this site -> http://gnupg.10057.n7.nabble.com/Exi...pt-td7342.html
I added the --homedir option with the PATH that I found in the error.log of apache to the gpg command and it works perfectly!
Thanks to all!
I have a CentOS 5.7 linux server and use php5.3.x.
On a pfSense system, you can restart services-that required root permissions using a php web page.
I'm trying to do something similar, I have written some php code to execute shell commands. For example, to restart the sshd service:
<?php
exec('/sbin/service sshd restart');
?>
and I tried to execute that command via exec function, but it needs root permission, but we have a apache user authority.
I have come across a few solutions:
"run apache with root user"
really unsafe. I do not want to do that.
"apache ALL=NOPASSWD:/sbin/service to /etc/sudoers"
I tried but and still have a problem.
Any other solutions?
Thanks for answers.
now.. it's interesting. i tried #refp post and it worked my local ubuntu server. But when i tried same at my cenOS vps server. It's not working.and that is apache's error log "rm: cannot remove `/var/lock/subsys/vsftpd': Permission denied"
Read this whole post before trying it out, there are choices to be made.
Solution using a binary wrapper (with suid bit)
1) Create a script (preferrably .sh) that contains what you want to be ran as root.
# cat > php_shell.sh <<CONTENT
#!/bin/sh
/sbin/service sshd restart
CONTENT
2) This file should be owned by root, and since it will later run with root permissions make sure that only root has permission to write to the file.
# chown root php_shell.sh
# chmod u=rwx,go=xr php_shell.sh
3) To run the script as root no matter what user that executes it, we will need a binary wrapper. Create one that will execute our php_shell.sh.
# cat > wrapper.c <<CONTENT
#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>
int
main (int argc, char *argv[])
{
setuid (0);
/* WARNING: Only use an absolute path to the script to execute,
* a malicious user might fool the binary and execute
* arbitary commands if not.
* */
system ("/bin/sh /path/to/php_shell.sh");
return 0;
}
CONTENT
4) Compile and set proper permissions, including the suid bit (saying that it should run with root privileges):
# gcc wrapper.c -o php_root
# chown root php_root
# chmod u=rwx,go=xr,+s php_root
php_root will now run with root permissions, and execute the commands specified in php_shell.sh.
If you don't need to the option to easily change what commands that will be executed I'd recommend you to write the commands directly in wrapper.c under step 4. Then you don't need to have a binary executing a external script executing the commands in question.
In wrapper.c, use system ("your shell command here"); to specify what commands you'd like to execute.
I would not have PHP execute any sudo commands. To me that sounds like asking for trouble. Instead I would create two separate systems.
The first system, in PHP (the web tier), would handle user requests. When a request is made that needs a sudo command I would place this request in some queue. This could be a database of some sort or middle-ware such as ZeroMQ.
The second system (the business tier) would read or receive messages from this queue and would have the ability to execute sudo commands but won't be in the scope of your web-server process.
I know this is a bit vague and it can be solved in different ways with various technologies but I think this is the best and safest way to go.
Allow the www-data user to run to run program1 and program2 with no password:
sudo visudo
Add to the contents of the sudoers file:
User_Alias WWW_USER = www-data
Cmnd_Alias WWW_COMMANDS = /sbin/program1, /sbin/program2
WWW_USER ALL = (ALL) NOPASSWD: WWW_COMMANDS
Save.
from https://askubuntu.com/questions/76920/call-a-shell-script-from-php-run-as-root
Solution using a binary wrapper (with suid bit)
Some modification of Filip Roséen - refp post.
To execute any command modified wrapper.c
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>
#include <string.h>
int main (int argc, char **argv)
{
setuid (0);
char cmd[100] = "";
int i;
char *p;
for(i=0; i < argc; i++) {
if(i != 0){
strcat(cmd, *(argv+i));
strcat(cmd, " ");
}
}
system (cmd);
return 0;
}
Compile and set proper permissions;
gcc wrapper.c -o php_root # php_root can be any name.
chown root php_root
chmod u=rwx,go=xr,+s php_root
Now call from PHP. Execute any command.
shell_exec('./php_root '.$cmd);//execute from wrapper
I recently published a project that allows PHP to obtain and interact with a real Bash shell, it will easily give you a shell logged in as root. Then you can just execute the individual bash commands rather than bundling then in a script. That way you can also handle the return. Get it here: https://github.com/merlinthemagic/MTS
After downloading you would simply use the following code:
$shell = \MTS\Factories::getDevices()->getLocalHost()->getShell('bash', true);
$return1 = $shell->exeCmd('service sshd restart');
echo $return1;
//On CentOS 7 output would be like:
//Redirecting to /bin/systemctl restart sshd.service
//On CentOS 6 and lower output would be like:
//Stopping sshd: [ OK ]
//Starting sshd: [ OK ]
setenforce 0
Write this command in the terminal this command will disable SELinux.
this isn't a good practice.
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.