F
F
faustoFF2013-02-04 18:00:37
PHP
faustoFF, 2013-02-04 18:00:37

Shell script as root from PHP?

Task :
use a PHP application to spawn some processes running from a specific (other than the user from which the web server is running) user.
Software:
Debian Linux
Apache
PHP
Now, as you can guess, processes running under its own user are spun off from apache, which is naturally not good for several reasons: 1) if you need to reboot apache (or God forbid it crashes on its own), then all processes generated from it will fall 2) crooked access rights for the www-data account due to the fact that it also needs the rights to launch application instances that lie outside the web server directory. Enough to endure this, I thought ...
Solution:
A shell script was written that can run the application as a specific user. It was tested as root through the console - it works. Through PHP, we execute shell_exec (), which runs our script with some parameters (conditionally, for ease of understanding, with a network port that the application instance will listen to). It remains to figure out the www-data rights to run the script as root. Well, there is also sudo, I thought ... This is where the difficulties arose.
Implementation:
Let's assume that the application binary is (conditionally) located here /home/app/bin . The username we are going to run the instances as has full access (rwx) to both the directory and the binary.
The web server files, as they should be, are lying around somewhere in / var / www. Apache is running as the www-data user.
The shell script is (conditionally) in /var/www/script.sh . Only root has full access rights (rwx) to it, everyone else cannot do anything with it. It carefully checks the input parameters (existence of the path, existence of the binary, and other checks) and launches the application instance with the following command:

su -s /bin/bash -c "cd $APP_PATH; ./$APP_BIN $APP_PARAMS > /dev/null 2>&1 &" "$USER_NAME"
or conditionally
su -s /bin/bash -c "cd /home/app/; ./bin -p 27100 > /dev/null 2>&1 &" username

It remains to let www-data run script.sh as root. Install sudo,
go to /etc/sudoers and add:
www-data ALL=(root) NOPASSWD: /var/www/script.sh

It feels like enough and for the same feeling of suspicion - too simple.
Now we call our script from PHP:
shell_exec("cd /var/www/; sudo ./script.sh -p 27100");

Doesn't work :(
Let's try it differently (via the console):
su -s /bin/bash www-data
cd /var/www/
sudo ./script.sh -p 27100

The little expected prompt to enter the www-data user password appears: What about NOPASSWD? And in general, what the hell is the password for www-data? :( Actually, what am I doing wrong? It is clear that the orthodoxy of the solution is, to put it mildly, in doubt, but for now I want to “finish off” at least it (the forces and time have already been spent). Other solutions will come (I hope) later with new experience .
[sudo] password for www-data:

Answer the question

In order to leave comments, you need to log in

4 answer(s)
F
faustoFF, 2013-02-04
@faustoFF

Problem solved. It's all about your own carelessness. My typo in the description helped me find a typo in the real configs in the same place (the path to the script in sudoers and the real path did not match) :) Now the script successfully executes from under www-data as root with the same rights.
It's funny, because of my own inattention, I generated such a discussion. I hope this will be useful to someone.

P
pawnhearts, 2013-02-04
@pawnhearts

firstly, you have /home/script.sh in sudoers, but it is in /var/www?
secondly, sudo has the -u option, why become root and call su from there, if you can immediately run from sudo under the desired user

P
pawnhearts, 2013-02-04
@pawnhearts

and yet, there is such a disown command, try using it instead of ">/dev/null 2>&1 &"

M
Max, 2013-02-04
@7workers

bash script respects all permissions, just because you were able to run script.sh as root doesn't mean everything inside script.sh will run as root. Try changing your script.sh to:
#!/bin/sh
foo() {
/bin/can /etc/passwd
}
export -f foo
su -c 'foo'

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question