Allowing PHP to execute a bash script with root pe

2019-01-23 20:20发布

how to allow a PHP script to execute a bash script with root permissions?

Let's say there is a PHP script...

<?php
// location: /var/www/script.php
exec("bash /var/scripts/test.sh"); // "sudo bash ..." does not work
?>

and a bash script ...

#!/bin/bash
# location: /var/scripts/test.sh
sudo mkdir /test

Of course PHP and Apache should not run as root and at best only the script can be executed with root permissions. Any ideas?

Best regards, Jimbo

标签: php bash exec root
6条回答
我欲成王,谁敢阻挡
2楼-- · 2019-01-23 20:39

You need to take a look at incron (cron for file system events). Have the php write to a file and set incron to launch your script on closure of the written to file (incron is very specific). Your script should probably also sanitize the input file to prevent code injection and use the lockfile command as well to prevent any race conditions between multiple web users.

I have a mini-web interface where one can turn on anonymous FTP or other services on for 1 hour with a password. www runs with normal privilages as does www-data (the php user) but incron calls the input handling script as root.

Mike

查看更多
该账号已被封号
3楼-- · 2019-01-23 20:46

Use a daemon running as root (maybe written in C), which starts the shell scripts for you. To trigger shell script execution from within the PHP script just use IPC (message queues).

Have a look here to get an idea what I am talking about: http://php.net/manual/en/function.msg-send.php#114831

查看更多
beautiful°
4楼-- · 2019-01-23 20:53

Any PHP-based solution that gives root rights at some point of the chain is dangerous: An attacker with access to the PHP user could gain access to the root user, and that is unacceptable from a security point of view.

I have never implemented this myself, but I'll suggest what I suggested here: Have a script/cron job with root rights frequently scan some location for a sign from the PHP script that a job is to be done - for example, a file with a certain name, or an entry in a jobs database.

If that file is found to exist, the root script does its thing, and removes the file again.

If your PHP script doesn't need direct response from the root script, I think this would be the best way to go. (A response could also be facilitated by the root script writing a status message into the file, of course).

As long as you closely limit what kinds of jobs PHP can write for the root script to do, this is a watertight solution, as it doesn't get the root user into PHP's business.

查看更多
兄弟一词,经得起流年.
5楼-- · 2019-01-23 20:54

If don't want wait for cron, here is a simple wrapper in C, what you will call from php.

#include <unistd.h>
#include <errno.h>
#define WEBUID 500
main( int argc, char ** argv, char ** envp ) {
    if( getuid() != WEBUID ) exit(1);
    /* some more security checks */
    if( setuid(geteuid()) ) perror( "setuid error" );
    envp = 0; /* don't want environment - security problem */
    system( "/hardcoded/path/to/script.bash", argv, envp );
}

This compiled wrapper should be owned as root, group "www" and should have "s-bit".
chwon root.www wrapper; chmod 4440 wrapper, so

  • when is executed his effective UID will be root
  • execute it can only group www (web-server's group)
  • and when the UID of the caller is not a web-server will exit
查看更多
再贱就再见
6楼-- · 2019-01-23 20:58

I recently published a project that allows PHP to obtain and interact with a real Bash shell (as root if requested), it solves the limitations of exec() and shell_exec(). 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('/my/bash/script.sh');
//the return will be a string containing the return of the command
echo $return1;

In terms of security it is far better than running apache as root. But letting PHP anywhere near root is always tricky.

The project i built achieves a root bash shell in one of 2 ways:

1) You allow apache the right to sudo python.

OR

2) You pass root credentials to the object every time you need a shell with root setup.

Pick your poison. :) Read the documentation.

查看更多
【Aperson】
7楼-- · 2019-01-23 21:01

You may not need PHP or Apache to run as root. If you have control of your server you might be able to use an Apache module called suPHP and specify the user you want to run Apache as for your php scripts in the config. You can do this on a site by site basis so you only need to run suPHP for scripts on a particular domain. I lack the expertise to advise you on how to install it, but I had our dedicated server company do it for me to allow a github post-receive hook to call a script on my dev server to trigger a git pull to the dev server any time someone pushes to the github repos. I was unable to get it to work any other way since Apache needs to run as the owner of the local repos for it to work.

I just thought of another possible solution based on the other comments here -- you might be able to write a simple php script to receives the request from the github hook and write some arbitrary info to a file in a directory with 777 permissions or to the db. Then have a cron job that checks that file or db every minute to see if it has changed and if so, issue the git pull request directly since cron usually runs as root already. You could even just see if the file's timestamp has changed to determine whether to do the git pull. You could have your cron script su to whatever user owned the repos and issue the git pull then. Not a true realtime solution, but if the cron script is very simple it wouldn't really bog down your system to call it every minute or two. Hope that helps.

查看更多
登录 后发表回答