Synology is reinforcing the security within its DMS, making more difficult the execution of scripts as root from packages. Here is my trick to do so based on the use of ssh and php.
Click to Read More
Theoretically, to run something as root, a user must be a sudoer, i.e.: a user having the right to execute commands as root. It’s not difficult to configure a user to be a sudoer. You simply have to add that user into a file located under /etc/sudoers.d/, with a few parameters to describe what he can execute and if he requires to type his password or not. Ex.: to let a user named “beatificabytes” able to execute the command ‘shutdown’ on a Synology:
- Create a file (the name does not matter): /etc/sudoers.d/beatificabytes
- Edit that file with vi (or nano if you installed that package). Notice that you should really be careful as any error in that file will prevent you to log in anymore: DANGER !!! That’s why it is usually highly recommended to use the command ‘visudo’ to edit such files (it checks the syntax before saving changes)… Unfortunately, this command is not available on Synology.
- To grant rights without having to type a password, type this: beatificabytes ALL=(ALL) NOPASSWD: /sbin/shutdown
The problem I have with this approach is that I have many various users (each package runs with its own user) and I don’t want to define them all as sudoers.
One option would be to run all packages with the same user who is defined as a sudoer. This is possible via a privilege file to be added into the packages (/conf/privilege).
But if like me you want to always use the same administrator account, who is already a sudoer, if you have php installed on your NAS and if you have enabled ssh, then your could simply open a ssh session with that admin account, from a php script, to execute your commands.
Here is the php script I am using for such a purpose (saved into a file named ‘sudo.php’):
<?php
$options = getopt("u:p:s:o:c:");
$user = $options['u'];
$password = $options['p'];
$server = $options['s'];
$port = $options['o'];
$command = $options['c'];
if (!function_exists("ssh2_connect")) die("php module ssh2.so not loaded");
if(!($con = ssh2_connect($server, $port))){
echo "fail: unable to establish connection to '$server:$port'\n";
} else {
// try to authenticate with username password
if(!ssh2_auth_password($con, $user, $password)) {
if (strlen($password) > 2){
$pass = str_repeat("*",strlen($password)-2);
} else {
$pass = "";
}
$pass = substr($password, 0,1).$pass.substr($password, -1);
echo "fail: unable to authenticate with user '$user' and password '$pass'\n";
} else {
// allright, we're in!
echo "okay: logged in...\n";
// execute a command
$command = "echo '$password' | sudo -S $command 2>&1 ";
if (!($stream = ssh2_exec($con, $command ))) {
echo "fail: unable to execute command '$command'\n";
} else {
// collect returning data from command
stream_set_blocking($stream, true);
$data = "";
while ($buf = fread($stream,4096)) {
$data .= $buf;
echo $buf;
}
fclose($stream);
}
}
}
?>
And to call it, from a shell for example, assuming that your are using php7.3, type something like:
php -dextension=/volume1/@appstore/PHP7.3/usr/local/lib/php73/modules/ssh2.so sudo.php -u YourAdminAccount -p YourAdminPassword -s 127.0.0.1 -o 22 -c "whoami"
Here above
- 22 is the port defined for ssh on my Synology
- I executed the command ‘whoami’. So, the outcome will be “root”
Et voilà.