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
Related
I want to do some tasks on my server that require root shell access. I want to make a simple API that I can access from PHP.
The things I want to achieve is:
clone from one database to another. The databases are owned by different users:
mysqldump -h localhost -u SOURCE_USER -pSOURCEPASSWD SOURCE_DB | mysql -h localhost -u DEST_USER -pDEST_PASS DEST_DB
copy files from one user public_html to another:
cp -R SOURCE_DIR DEST_DIR
I have working bash-scripts for both those tasks.
I do not want to give PHP full root access to the server, since that would be crazy, but instead:
How can I make specified bash-scripts executable from a PHP-file in one linux-user's public_html directory?
Alternatively: How can I give root shell access (via shell_exec) to ONE specified PHP-file on a server.
You could use this project: Github. It allows PHP to obtain and interact with a real Bash shell even as root without running the web server as root.
After composer/downloading you would simply use the following code:
//read the documentation: here you get a root shell if you allowed sudo
$shellObj = \MTS\Factories::getDevices()->getLocalHost()->getShell("bash", true);
//OR if you did not want to give the webserver sudo access, then you can use this syntax:
$shellObj = \MTS\Factories::getDevices()->getLocalHost()->getShell("bash", false);
\MTS\Factories::getActions()->getRemoteUsers()->changeUser($shellObj, 'root', 'rootPassword');
//In both cases you now have a shell as root. This really is a bash shell, its not just wrapping the PHP shell functions.
//All you have left is to issue commands just like you would on a bash prompt
$strCmd = "mysqldump -h localhost -u SOURCE_USER -pSOURCEPASSWD SOURCE_DB | mysql -h localhost -u DEST_USER -pDEST_PASS DEST_DB";
//for the vast majority of commands that finish within 10 sec you need only issue the command
$return = $shellObj->exeCmd($strCmd);
echo $return;// return from your command
//However if your command runs for more than 10 sec, you must set a timeout. e.g.
//timeout in miliseconds
$timeout = 20000;
$return = $shellObj->exeCmd($strCmd, null, $timeout);
echo $return;// return from your command
Feel free to issue more commands on the $shellObj, its a bash shell ready to take orders and as i said ready the documentation.
After an useful comment from arkascha I researched sudo and found Ezequiel Hdez's answer in sudo in php exec() to be useful in finding the answer to my question:
Allow myuser to sudo my shell script by adding in sudoers file (access it by typing visudo):
myuser ALL = NOPASSWD: /path/to/myscript.sh
Make script executable:
chown u+x /path/to/myscript.sh
Then in PHP (from "myuser")
exec("sudo /path/to/myscript.sh argument1 argument2");
Now I was able to do whatever I want from PHP, but ONLY via /path/to/myscript.sh
Been wrestling with this one for a little bit. I'm currently working on a PHP application that connects to a custom API as well as performs changes to a server via Phpseclib's SSH2 library.
$ssh = new Net_SSH2($server_name);
if(!$ssh->login("username", "password")) {
$result['result'] = 'ERROR';
$result['message'] = 'Login failed';
} else {
$result['propertyFolderDeleted'] = $ssh->exec("cd /var/www/sites; echo 'password' | sudo -S /usr/local/bin/delete_property.sh -sc $company_name -sp $property_name");
return '{"data":'.json_encode($result).'}';
}
Output generated:
{"data":{"propertyFolderDeleted":"[sudo] password for portals: "}}
Pretty straight-forward, my application uses SSH2 to exec some Bash scripts I have in place on my server. For the most part this works flawlessly, but for some reason, exec-uting this one Bash script ('delete_property.sh') outputs the sudo password prompt as a result.
I've tweaked my request and executing my Bash script via command-line (in Putty) no longer outputs the prompt text upon completion of the Bash script.
Why isn't this the case when using Phpseclib?
Just add the user to the sudorious file.
Open the terminal.
Type "sudo visudo"
Add at the end of the file "youruser ALL=(ALL) NOPASSWD:ALL" and just replace "youruser" with your real user.
Save and exit.
Now every one command with your user which is using sudo will be executed without asking the password.
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 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.