I want to execute a command as root with shell_exec. Now I know this is dangerous, but believe me, you need to login with MOD_AUTH and have the right privilleges to come to this page. It's secure. How can I get this done?
You could use the latest SVN version of phpseclib, a pure PHP SSH implementation, to do this. eg.
<?php
include('Net/SSH2.php');
$ssh = new Net_SSH2('www.domain.tld');
$ssh->login('username', 'password');
$ssh->read('[prompt]');
$ssh->write("sudo command\n");
$ssh->read('Password:');
$ssh->write("Password\n");
echo $ssh->read('[prompt]');
?>
The problem isn't that your page is or isn't secure, the problem is that giving a php page the ability to run some sudo command would give it to all pages including any injected code on any insecure page on any site on the server.
That said, it might be best to make a wrapper script that does just the one job that needs doing, then give the http user access to just that ONE command as sudo
http ALL=(ALL) NOPASSWD:/user/local/bin/your_wrapper_script.sh
Definitley not advised. However, you will want to look into editing the sudoers file and add the user php is running as a NOPASSWD for the command you need to run. This will only allow him to sudo that one command with out entering a password.
If you need more commands add more to it. Sudoers Configuration I know that forum/post is debian based but sudo is not strictly debian and that should help you out with the sudo configuration values that you need to put it.
I just Google'd for php sudo shell_exec and this came up as the #1 match:
http://www.php.net/manual/en/function.shell-exec.php#101440
ilya at linemedia dot ru 16-Dec-2010 04:36
sudo can be executed without storing pass in a file
system('echo "PASS" | sudo -u root -S COMMAND');
$aux=echo "admin-pass" | your command;
echo $aux;
/*******************************
************Example*************
*******************************/
Run a Perl script named my_perl_script.pl:
$aux=echo "admin-pass" | sudo -u root -S perl /path-to-the-script/my-perl-script.pl;
echo $aux;
Best way to do it:
$descriptorSpec = array(
0 => STDIN,
1 => STDOUT,
2 => STDERR,
);
if (posix_getuid() === 0) {
echo "Root\n";
} else {
echo "No root\n";
$command = 'sudo ' . PHP_BINARY . ' ' . implode(' ', $_SERVER['argv']);
$pipes = [];
$process = proc_open($command, $descriptorSpec, $pipes);
if (is_resource($process)) {
proc_close($process);
}
}
It runs the same command again, with sudo prefixed.
Related
I have scripts in /etc/init.d/ that I use to control game servers and I would like to build a simple web interface to call those scripts. My sudoers file contains something like
www-data ALL=(ALL) NOPASSWD: /etc/init.d/starbound start stop
When I execute sudo /etc/init.d/starbound start within PHP, nothing happens. Am I missing something? Trying to access paths my PHP user is not allowed to usually gives me the appropriate warnings at least.
Using sudo requires that you input your password when you run a command. By running sudo with exec() you aren't providing the password to sudo and cannot run the command with root level privileges.
Ubuntu.SE provides a way to pass the password to sudo in a single command, but the result is a little messy when implemented with PHP because the Password: prompt will be sent to STDOUT when the call is made, but that can be silenced by sending the output to /dev/null. The result of the command can still be stored in a variable as you might expect.
<?php
//Kill a sudo session if one exists.
exec('sudo -k');
//Run sudo without authenticating
$output = exec('sudo echo "foo"');
var_dump($output); //string(0) ""
//Provide the password and pipe it into sudo.
$output = exec('echo "password" | sudo -S echo "foo" 2> /dev/null');
var_dump($output); //string(3) "foo"
?>
Seems the problem lies in the sudoers file. If I remove the start stop, it works.
So a correct sudoers could look like this:
Cmnd_Alias GAMES = /etc/init.d/ark_thecenter start, \
/etc/init.d/ark_thecenter stop, \
/etc/init.d/ark_theisland start, \
/etc/init.d/ark_theisland stop, \
/etc/init.d/starbound start, \
/etc/init.d/starbound stop
www-data ALL=(ALL) NOPASSWD: GAMES
I have a problem doing Sudo command through SSH when connecting from php, but not connection from regular terminal
if i'm connecting on SSH to an AWS machine with Net_SSH2
$ssh = new Net_SSH2($instanceIp);
if ( ! $ssh->login('ec2-user', $key)) {
$logger->error('Login Failed');
}
I'll get this error: sudo: sorry, you must have a tty to run sudo
If I'm connecting directly from terminal
ssh -i ~/Path/to-file-key.pem ec2-user#111.111.11.111
So I can run any sudo command without problems.
I don't want to remove from /etc/sudoers (I don't want to have something to do on the server, I want it to be done by the connection)
Defaults requiretty
Is there a way to do it without that ?
Thanks for your help
If i may quote this article,
Red Hat systems (RHEL, Fedora...) have been known to require a TTY in default sudoers file. That provides no real security benefit and can be safely removed.
Red Hat have acknowledged the problem and it will be removed in future releases.
Therefore, it's safe to remove the "requiretty", that way you won't have a problem to execute sudo commands via SSH.
You may also try running ssh with the -t option(the repercussions of which you can find in the aforementioned article), it forces pseudo-tty allocation, so it might work. I don't know if there's a way to add that option to Net_SSH, but it should be OpenSSH based, so normally, you should.
Worst case scenario, you can allways run the ssh command via exec, but removing require tty seems to be the best option.
The phpseclib docs give an example of how to use sudo:
<?php
include('Net/SSH2.php');
$ssh = new Net_SSH2('www.domain.tld');
if (!$ssh->login('username', 'password')) {
exit('Login Failed');
}
echo $ssh->read('username#username:~$');
$ssh->write("sudo ls -la\n");
$output = $ssh->read('#[pP]assword[^:]*:|username#username:~\$#', NET_SSH2_READ_REGEX);
echo $output;
if (preg_match('#[pP]assword[^:]*:#', $output)) {
$ssh->write("password\n");
echo $ssh->read('username#username:~$');
}
http://phpseclib.sourceforge.net/ssh/examples.html#sudo
If you want to try to do it with $ssh->exec (it's not clear what you're doing since you didn't provide the full code in your post) you can do sudo visudo and then add an entry for the username / script that you're wanting to run. eg.
username ALL=(ALL) NOPASSWD: /path/to/script
Alternatively, you could do this:
echo "PASSWORD" | sudo -S /path/to/script
For more information google "sudo in a bash script"
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
How to call shell script from php that requires SUDO?
I have a Python file that needs SU rights to run (on Ubuntu server).
Can't figure out how to do it.
Running it from PHP like so:
$command = "python /path/to/my/file.py params";
$temp = exec($command, $output);
var_dump($output);
Not working. (Xvfb fails to start for non-root)
Tried:
$command = "echo 'root_pwd' | sudo -S python /program.py params"
...
didn't work.
Tried: edit /etc/sudoers:
Cmnd_Alias BUNDLE = /path/to/myprog.py
nobody ALL=(ALL) NOPASSWD:BUNDLE
and then:
$command = "sudo -u nobody python myprog.py params";
...
didn't work.
When I say "didn't work" - I mean that var_dump($output) returns empty array, no successful result on server (myprog.py should generate a file on the server) or the page simply loads for a couple mins until it times out.
Basic .py files (that don't require special rights) work.
Pls help.
PS:
.Py file is making screenshot of URL, so is using webkitgtk, Xvfb and couple other things.
Your command is wong:
$command = "sudo -u nobody python myprog.py params";
Here you're calling the python interpreter directly, but in your sudores file you only allowed /path/to/myprog.py.
If you want to do it this way, then add a shebang to your python program and make it executable, then change your command to
$command = "sudo -u nobody /path/to/myprog.py params";
But for this to work, the user you specify in your sudoers file must be the user executing the command, which probably isn't nobody but the web server process (www-data?):
Cmnd_Alias BUNDLE = /path/to/myprog.py
www-data ALL=(ALL) NOPASSWD:BUNDLE
The other way you tried
$command = "echo 'root_pwd' | sudo -S python /program.py"
probably failed because of two reasons:
the current user (probably the webserver process) isn't allowed to sudo
sudo doesn't take the root password, but the current users password
And you don't really want to pass passwords like this anyway...
I have a php script which contains su. when I run it in shell it ask for root password and works well. but now I want make an interface for it. as you know all command in php-apache runs as www-data user and this user doesn't have specified password or it's not in sudoers. so I can't use "echo pass | sudo -S ..." because I don't know what is www-data's password and It is not logical on every server set password for www-data or add it in sudoers+nopass, is it?
What solution can you suggest to solve this problem?
one of my commands:
su -c \"/usr/sbin/dmidecode -s baseboard-serial-number | tr \ \-\"
phpseclib should be best library choice as it does not requires any additional extensions.
<?php
include('Net/SSH2.php');
$ssh = new Net_SSH2('example.com');
if (!$ssh->login('user', 'pass')) {
exit('Login Failed');
}
echo $ssh->exec('whoami');
echo $ssh->exec('pwd');
?>
Another alternative is libssh2, but it has to be compiled separately and is notoriously difficult to setup/use.
I recently published a project that allows PHP to obtain and interact with a real Bash shell, you can easily get a shell with root. 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);
$strCmd = "\"/usr/sbin/dmidecode -s baseboard-serial-number | tr \ \-\"";
$return1 = $shell->exeCmd($strCmd);
echo $return1;// return from your command
I don't know what the deal is here…
So I want to run an applescript: sudo osascript myscript.scpt
This works fine in the terminal, but not when I execute it via PHP's exec(); nothing happens. The console says
no tty present and no askpass program specified ; TTY=unknown ; …
I did my research, and it seems I'm missing the password for the sudo command. I tried a couple different ways to get around this, including:
writing %admin ALL=(ALL) ALL in /etc/sudoers
and proc_open() instead of exec()
none of which seem to be working, consequently driving me CrAzY!
So basically, is there a clear-cut way to get PHP to execute a simple terminal command?
EDIT: to clarify, myscript.scpt is a simple appleScript that changes the onscreen UI (for a larger project). In theory, simply osascript myscript.scpt should be enough, however the sudo is for some reason necessary to invoke some response from the system. If the sudo could be somehow eliminated, I don't think I would be having this permissions problem.
It sounds like you need to set up passwordless sudo. Try:
%admin ALL=(ALL) NOPASSWD: osascript myscript.scpt
Also comment out the following line (in /etc/sudoers via visudo), if it is there:
Defaults requiretty
I think you can bring specific access to user and command with visudo something like this:
nobody ALL = NOPASSWD: /path/to/osascript myscript.scpt
and with php:
#exec("sudo /path/to/osascript myscript.scpt ");
supposing nobody user is running apache.
php: the bash console is created, and it executes 1st script, which call sudo to the second one, see below:
$dev = $_GET['device'];
$cmd = '/bin/bash /home/www/start.bash '.$dev;
echo $cmd;
shell_exec($cmd);
/home/www/start.bash
#!/bin/bash
/usr/bin/sudo /home/www/myMount.bash $1
myMount.bash:
#!/bin/bash
function error_exit
{
echo "Wrong parameter" 1>&2
exit 1
}
..........
oc, you want to run script from root level without root privileges, to do that create and modify the /etc/sudoers.d/mount file:
www-data ALL=(ALL:ALL) NOPASSWD:/home/www/myMount.bash
dont forget to chmod:
sudo chmod 0440 /etc/sudoers.d/mount
I recently published a project that allows PHP to obtain and interact with a real Bash shell. Get it here: https://github.com/merlinthemagic/MTS
The shell has a pty (pseudo terminal device, same as you would have in i.e. a ssh session), and you can get the shell as root if desired. Not sure you need root to execute your script, but given you mention sudo it is likely.
After downloading you would simply use the following code:
$shell = \MTS\Factories::getDevices()->getLocalHost()->getShell('bash', true);
$return1 = $shell->exeCmd('/path/to/osascript myscript.scpt');
Run sudo visudo command then set -%sudo ALL=(ALL:ALL) to %sudo ALL=(ALL:ALL) NOPASSWD: ALL it will work.
I had a similar situation trying to exec() a backend command and also getting no tty present and no askpass program specified in the web server error log. Original (bad) code:
$output = array();
$return_var = 0;
exec('sudo my_command', $output, $return_var);
A bash wrapper solved this issue, such as:
$output = array();
$return_var = 0;
exec('sudo bash -c "my_command"', $output, $return_var);
Not sure if this will work in every case. Also, be sure to apply the appropriate quoting/escaping rules on my_command portion.
The best secure method is to use the crontab. ie Save all your commands in a database say, mysql table and create a cronjob to read these mysql entreis and execute via exec() or shell_exec(). Please read this link for more detailed information.
killProcess.php
I think directly calling a sudo command might be difficult because you are setting up the whole server to work without a password.
Perhaps as an alternative you could setup a CRONjob as root and monitor a flag file. Once the flag file exists it will run the osascript myscript.scpt and then delete the flag file.
This way you will keep SUDO secure from a config point of view and the server safer. To run the script you just need to touch the flag file from PHP.
It would of course introduce a delay of however many minutes you running the CRON job. It would also mean that you would have to redirect the output to a file and have a async monitor of the output, but it will depend on your application if this is a problem or not.
But it is an alternative that might protect the server.