Execute root commands via PHP

98,002

Solution 1

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.

Solution 2

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.

Solution 3

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 4

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

Solution 5

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  ]
Share:
98,002
Admin
Author by

Admin

Updated on July 09, 2022

Comments

  • Admin
    Admin almost 2 years

    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:

    1. "run apache with root user" really unsafe. I do not want to do that.
    2. "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"

  • Admin
    Admin over 12 years
    That code from test.php. for execute bash script. <?php exec('./php_root.sh'); ?> and here php_root.sh codes #!/bin/bash /sbin/service vsftpd stop and i did you chmod and chow commands. and still dont work. here is the error.log output "rm: cannot remove `/var/lock/subsys/vsftpd': Permission denied"
  • Admin
    Admin over 12 years
    and problem SOLVED with refp answers. i forgot add /sbin path to command in php_shell.sh.. thank you every much!!
  • Admin
    Admin over 12 years
    @refp i flaged your post "accept" i guess. thank you for interest and help. how can i give rep to you ?
  • Piyuesh
    Piyuesh over 10 years
    I've done all 4 steps mentioned above and still getting permission denied error on CentOS 6. Has anyone faces same issue ?
  • Bruno Braga
    Bruno Braga almost 10 years
    hello.. im trying to get this to work, but i can't :( if i execute from ssh php test.php i can get put it to work, but if i execute the file via browser www.domain.com/teste.php i can't execute the command!!:( any help? thank you
  • Jack
    Jack almost 8 years
    Lots of errors trying to run this on my centos 6.7 server. Fixed a couple of them then decided to give up.
  • MerlinTheMagic
    MerlinTheMagic almost 8 years
    Head over to github and open a new issue documenting the error you got.
  • Jack
    Jack almost 8 years
    Does php_root have to be replaced with my apache user?
  • Admin
    Admin over 7 years
    I prefer this over compiling an executable to do the stuff. For sure the best method would be SuExec if you have time to set it up.
  • Rahul
    Rahul over 7 years
    @FilipRoséen-refp I'm trying to use this method to run a python cgi script as root from a http form (<form action="/cgi-bin/php_root" method="POST">). However, the POST variables are always None in the Python script. I'm assuming the POST variables are passed on to the C code and I should extract them there and send them to the python script as arguments? Could you tell me how I could do that?
  • Araw
    Araw about 7 years
    It may a stupid question: But why do we create a script when everything can be done in the executable written in C? First we create an application in C to tell that to execute a shell script. Why not just do everyting in C?
  • 1myb
    1myb almost 7 years
    @FilipRoséen-refp I've tried to call the script with <?php $message=shell_exec('./php_root 2>&1'); print_r($message);?> but it returning error sh: ./php_root: Permission denied The php file is own by apache:apache
  • 1myb
    1myb almost 7 years
    @FilipRoséen-refp this line is not working for me? setuid (0); I've run the gcc and now the error is Permission denied /var/www/html/x/php_shell.sh
  • Joel G Mathew
    Joel G Mathew almost 7 years
    @Araw Because if you need more than a few lines of bash code, or need loops or conditions, it can only be done from a script file.
  • mlerley
    mlerley over 5 years
    It should be clarified here that you need to add sudo to the beginning of your command when using this method.
  • MaXi32
    MaXi32 over 4 years
    This is like creating a rootkit place it in your own system and waiting for somebody to view the php source code and trigger any commands to access directly into your linux system.
  • Steve Moretz
    Steve Moretz about 3 years
    Amazing that was genius.
  • Kevin M
    Kevin M about 3 years
    This is very dangerous. This binary wrapper will allow for any system command to be executed with root privileges. If anyone manages to gain unauthorized access to your website, they will have full root access to your entire server. From a security perspective, this is the same as writing the root password in plain text in the php script such as shell_exec('echo <root_password> | sudo -S <cmd>');