General Considerations
Whenever using SSH, password authentication should be avoided, i.e. the /etc/ssh/sshd_config file should contain the following lines:
PermitRootLogin no
PasswordAuthentication no
However, if one - for some reason - has to use password authentication, one should use established, well known and tested tools, like sshpass. Do not start to pipe around passwords by yourself.
If using pubkey authentication it does not make sense to protect the private key by a passphrase, if the passphrase is in turn stored inside a config file or alike. If an attacker is able to gain filesystem read access to steal the private key file, he will also be able to steal the config file.
All commands that can run with user privileges, should run with user instead of root privileges.
The used programming language will not be considered in this answer, since there is no difference between Python's subprocess.call
, Java's java.lang.Runtime.exec
or a subshell environment inside a shell script with regards to security.
Further hardening the remote host against external attackers by configuring a firewall, putting IDS/IPS systems in place and the like will also not be considered, since it is out of scope.
That said, let us consider different scenarios:
Running Commands of Which a Finite Subset Requires Root Privileges
One should use a separate user (adduser --shell /bin/rbash --disabled-password remcmdexec
will create a user with a restricted shell, not able to do local but only remote logins, see man adduser
and man rbash
) in combination with a sudoers file that allows this user to only run the required, finite set of commands as root (see man sudoers
) on the remote host:
# /etc/sudoers
remcmdexec ALL = (root:root) NOPASSWD: /usr/bin/systemctl reload some.service
Requiring a password to run these commands with sudo
does not make sense, since local login was disabled (--disabled-password
parameter) and an attacker who was able to steal the key file will also be able to steel the required password (see answer's first section).
The authorized_keys file should contain further restrictions to prevent e.g. port forwarding, see man sshd
:
restrict ssh-rsa <BASE64-PUBKEY-REPRESENTATION> remcmdexec
It should further be owned by root and being read- but not writable by the remcmdexec user, to prevent removal of SSH restrictions:
$ ls -l /home/remcmdexec/.ssh/authorized_keys
-rw-r--r-- 1 root root 739 Sep 18 22:47 /home/remcmdexec/.ssh/authorized_keys
Invoke e.g. ssh remcmdexec@remhost sudo /usr/bin/systemctl reload some.service
for a command that requires root privileges. For all other commands skip sudo
.
Running Commands of Which a Nonfinite but Proper Subset Requires Root Privileges
The same setup as presented at the answer's previous section can be used, but the sudoers file needs to be adapted:
remcmdexec ALL = (ALL:ALL) NOPASSWD: ALL
This is, because remcmdexec finally needs to gain root privileges. Understand that an attacker who is able to login as remcmdexec is now able to remove each and every restriction put in place on the remote host, no matter how intricately the way to achieve root privileges was designed. Therefore all those restrictions are futile in regards to security (A willing attacker). However, they are not futile in regards to safety (System failures).
Running a Nonfinite Set of Commands of Which All Require Root Privileges
It does no longer make sense to use sudo
. Instead login in as a user with root privileges to run a command: ssh root@remhost /usr/bin/somecmd
Therefore the following line has to be present at the /etc/ssh/sshd_config file:
PermitRootLogin prohibit-password
However, keep the restrictions inside the authorized_keys file to preserves some basic safety.
Best Answer
A portable solution would be:
However, as google-chrome is requiring X11 access, this will likely fail unless you unsecured it, which would be a very bad idea, especially while running as root.
If X11 tunelling/forwarding is allowed, a better way would be
or