什么是好的设置,允许使用 SSH 在具有权限的远程服务器上自动执行命令或脚本root
?
我知道(只是模糊地知道一些选项)以下选项:
- 允许直接登录
root
(PermitRootLogin
)(并且可能强制密钥认证)。 - 配置
sudo
不需要密码(NOPASSWD
标志在sudoers
) 和 TTY (requiretty
标志)。 - 配置
sudo
为在使用特定私钥进行身份验证时允许执行特定命令/脚本。 - 将脚本所有者设置为
root
并设置setuid 权限。
但首先,我不确定这些会带来什么安全后果。例如,我知道允许root
登录是不被认可的。但我不确定,如果这不是一个过时的观点。据我所知,密码验证似乎很危险。使用公钥验证,直接登录root
可能没问题。对于某些选项,特别是sudo
,我甚至不确定所需的配置。虽然我能够用谷歌搜索所有这些,但可能会有一些我可能错过的安全考虑,这就是为什么我要征求专家的意见。
请注意,我要求的是服务器端设置。执行将由程序触发,而不是像这样的工具ssh
,所以我不是在寻找自动客户验证。
背景:积极参与ssh
Stack Overflow 上的标签经常出现的问题之一是关于人们在尝试root
使用各种编程语言(C#、Java、VB.NET、Python 等)和 SSH 库(SSH.NET、JSch、Paramiko 等)的帐户通过远程 Unix/Linux 服务器上的 SSH 执行命令/脚本(甚至是 SFTP 服务器)时尝试的各种黑客攻击。
人们尝试的实现通常尝试使用su
或sudo
。然后这些会提示输入密码。因此,实现会尝试将密码输入到命令输入中。由于su
和sudo
经常需要终端仿真对于密码提示,实现必须要求 PTY。这反过来又会造成进一步的麻烦,因为与终端仿真的会话通常使用交互式功能,例如ANSI 转义代码、分页等。所有这些都导致了大量不可靠的黑客攻击,试图删除甚至解释 ANSI 转义码或模拟足够大的终端以避免分页。
以下列举众多示例中的几个:
- 使用 JSch 执行的“sudo”命令需要密码,即使在交互式 SSH 会话中不需要密码
- 使用 Python 中的 Paramiko 模块切换到 root 用户时出现“必须从终端运行”的情况
- 使用 Python 在 SSH 中使用“su -l”执行命令
- 当必须切换用户时使用 JSch 到 SFTP
虽然我通常可以提供实施这些黑客的帮助,但我通常也会建议有比自动化更好的方法sudo
。su
但我实际上并不确定是否能提供这些所谓的“更好的方法”. 相关问题:sudo
几乎沒有用嗎?
所以我正在寻找典范从超级用户的角度回答,然后可以参考并改编以用于 Stack Overflow 的目的。
答案1
一般注意事项
每当使用 SSH 时,密码认证应该避免,即/etc/ssh/sshd_config文件应包含以下行:
PermitRootLogin no PasswordAuthentication no
然而,如果出于某种原因必须使用密码认证,应该使用已建立的、众所周知的和经过测试的工具,例如密码. 不要自己开始传输密码。
如果使用公钥认证如果密码存储在配置文件或类似文件中,则用密码保护私钥是没有意义的。如果攻击者能够获得文件系统读取权限来窃取私钥文件,那么他也能够窃取配置文件。
所有可以运行的命令用户权限,应该运行用户代替根特权。
该答案不会考虑所使用的编程语言,因为在安全性方面, Python
subprocess.call
、Java或 shell 脚本内的子 shell 环境之间没有区别。java.lang.Runtime.exec
通过配置防火墙、建立 IDS/IPS 系统等来进一步加强远程主机对外部攻击者的防御能力也不会被考虑,因为这超出了范围。
话虽如此,让我们考虑一下不同的情况:
运行命令有限子集需要 Root 权限
应该使用一个单独的用户(adduser --shell /bin/rbash --disabled-password remcmdexec
将创建一个具有受限 shell 的用户,不能进行本地登录,只能进行远程登录,请参阅man adduser
和man rbash
)与sudoers文件,允许此用户仅运行所需的有限命令集根(参见man sudoers
)在远程主机上:
# /etc/sudoers
remcmdexec ALL = (root:root) NOPASSWD: /usr/bin/systemctl reload some.service
要求输入密码来运行这些命令sudo
是没有意义的,因为本地登录已被禁用(--disabled-password
参数),并且能够窃取密钥文件的攻击者也将能够窃取所需的密码(参见答案的第一部分)。
这授权密钥文件应包含进一步的限制以防止例如端口转发,请参阅man sshd
:
restrict ssh-rsa <BASE64-PUBKEY-REPRESENTATION> remcmdexec
它应该进一步归根并且可由删除远程命令用户,为防止删除 SSH 限制:
$ ls -l /home/remcmdexec/.ssh/authorized_keys
-rw-r--r-- 1 root root 739 Sep 18 22:47 /home/remcmdexec/.ssh/authorized_keys
例如调用ssh remcmdexec@remhost sudo /usr/bin/systemctl reload some.service
需要的命令根权限。对于所有其他命令,请跳过sudo
。
运行命令非有限真子集需要 Root 权限
可以使用与答案上一节中介绍的相同的设置,但sudoers文件需要修改:
remcmdexec ALL = (ALL:ALL) NOPASSWD: ALL
这是因为删除远程命令最终需要获得根权限。了解能够以以下身份登录的攻击者删除远程命令现在可以删除远程主机上设置的每个限制,无论实现的方式多么复杂根特权的设计。因此,所有这些限制对于安全(自愿攻击者)。然而,他们对于安全(系统故障)。
运行非有限集命令全部需要 Root 权限
使用 不再有意义sudo
。而是使用根运行命令的权限:ssh root@remhost /usr/bin/somecmd
因此,必须有以下一行/etc/ssh/sshd_config文件:
PermitRootLogin prohibit-password
然而,保持限制在授权密钥文件保存了一些基本安全。
答案2
我认为,对于大多数简单情况(例如,如果像 Puppet/Chef/CfEngine/Ansible 这样的框架是多余的),但需要对远程系统进行高水平的控制,那么一个合适的解决方案就是
(a) 要求基于密钥的身份验证 (b) 锁定 SSH 可以使用的位置 - 特别是锁定 root 用户可以使用的 IP 地址 (c) 确保具有这种信任关系的机器得到适当的保护。
我认为“以 root 身份登录不受欢迎”并不令人反感,但“以 root 身份登录并执行不需要 root 权限的操作”却令人反感。密码容易被猜到,因此帐户可能被暴力破解,因此这是一个需要解决的问题,允许人们以 root 身份登录,他们可以犯下范围更广的愚蠢错误,并做一些隐藏恶意活动的可疑事情 - 但根据架构的不同,这可能实际上没有意义。
这XKCD 通讯指出,根据环境的不同,根帐户是否受到损害实际上可能并不重要。
对于一般情况来说,最简单、最有效的解决方案可能是严格限制谁可以以 root 身份登录通过控制密钥并指定 /etc/ssh/sshd.conf 中适当的 AllowUsers 行。允许普通用户但锁定 root 访问权限的适当行可能如下所示:
AllowUsers normaluser1 normaluser2 [email protected]
当然,重要的是不允许基于密码的登录,或者根帐户没有密码(即在密码文件的密码字段中有“!”或“*”)。
正如您所假设的,如果只需要运行一个(或少数)程序,那么最好设置一个具有基于密钥的身份验证的特定用户,并允许适当的 sudo 访问所需的命令。
当然,有很多方法可以进一步“锁定”访问权限,具体取决于数据的价值 - selinux、远程日志记录、受限 shell、每日时间限制、登录时立即通知、主动日志监控(如 fail2ban)[以及我认为非可选的网络限制] 都可以成为解决方案的一部分。也就是说,如果您只是控制一个可以轻易摧毁和重建的系统,那么其中很多可能都是过度的。
请记住,安全性是层层构建的,为了能够获得 root 访问权限,帐户需要通过多个层级。锁定访问权限、SSH 私钥、防火墙、每日时间限制 [ 以及最小访问原则,即仅提供对所需内容的访问权限,不提供更多访问权限、日志记录、备份 ] 应共同发挥作用,成为良好安全性的一部分。
附加 - SUDO 访问
Sudo 是一种允许普通用户以提升的访问权限运行某些命令的机制,它非常灵活,适用范围也非常广泛。虽然 sudo 的简要介绍在这里并不合适(但如果您输入男人须藤在大多数发行版中,适当的步骤可能是 -
编辑 /etc/sudoers - 大多数 Linux 版本都有一个特殊程序来执行此操作,称为“visudo”,需要以 root 身份运行,大致相当于使用系统编辑器编辑 /etc/sudoers(这是执行此操作的另一种方法 - 尽管可能不常见)
添加/更改适当的行以允许给定用户执行特定操作。例如,如果您希望他们能够挂载目录而不必输入密码,您可以输入如下行:
username ALL=/sbin/mount NOPASSWD: ALL
要运行此命令,适当的用户将运行类似
sudo mount /dev/xxx /path/to/mount
您可以为多个命令列出多行,使用组而不是使用 - sudoers 是一个相当灵活的子系统。在许多发行版中,还可以将带有命令的文件添加到子目录,如 /etc/sudoers.d
答案3
以下是 Unix Stackexchange 帖子中的回答
如何远程执行 ssh 命令,无需密码即可执行 sudo 命令。
此方法允许服务器管理员允许您的帐户执行一条命令而sudo
无需指定密码。该命令可能是对您的脚本的调用,并且仅在您的帐户下运行时才允许。由于允许的命令是完全指定的,包括参数,因此我相信这种方法非常安全。
您可以告诉 sudo 跳过某些命令的密码。
例如
/etc/sudoers
archemar ALL = (www-data) NOPASSWD: /bin/rm -rf /var/www/log/upload.*
这让我可以使用
sudo -u www-data /bin/rm -rf /var/www/log/upload.*
如同 archemar 一样,无需密码。
注意
sudo -u www-data rm -rf /var/www/log/upload.*
不起作用(会要求输入密码),因为
rm
与 不同/bin/rm
。确保
/etc/sudoers
使用visudo
命令进行编辑。一旦您达到高级水平,您可能希望拥有自己的
sudo
文件/etc/sudoers.d
。
答案4
这是有关安全考虑的答案,我认为其他答案中尚未解决这个问题。
有什么好的设置可以允许使用 SSH 在具有 root 权限的远程服务器上自动执行命令或脚本?
这包括多个部分:允许以提升的权限(root)执行单个脚本或命令,以及使用 SSH。这些不一定是相互依赖的。
- 允许 root 直接登录 (PermitRootLogin)(并可能强制密钥认证)。
这将允许任何人拥有完全的 root 权限(不限于您的单个命令/脚本)。它还允许任何人尝试通过尝试密码等方式远程侵入您的系统。
- 配置 sudo 不需要密码(sudoers 中的 NOPASSWD 标志)和 TTY(requiretty 标志)。
只要用户登录,这将允许任何用户拥有完全的 root 权限。从安全性方面来说,它并不比允许 root 登录好多少,尽管自动尝试侵入其他用户帐户的次数会更少。
- 配置 sudo 以允许在使用特定私钥进行身份验证时执行特定命令/脚本。
我不确定这将如何实现 - sudo 对 SSH 密钥一无所知,至少我熟悉的 sudo 变体是这样的。
从安全角度来看,将 sudo 配置为仅允许执行特定的命令/脚本要好得多(因为它更具限制性)。
- 将脚本/命令所有者设置为root并设置setuid权限。
这将允许任何用户以 root 身份执行此脚本。您无法将此限制为特定用户,并且 setuid 位本身也存在潜在的安全漏洞。
最后,我认为没有一个典范答案 - 最佳解决方案取决于您的情况和要求。因此,就像所有与安全相关的事情一样,您首先要坐下来明确要求:您希望有多宽容和灵活?实际用例是什么?您需要将系统约束得多紧密?等等。
话虽如此,让我添加一个你没有提到的非常严格的替代方案:
创建一个仅用于执行特定脚本/命令的特定用户帐户。仅允许使用密钥对通过 SSH 登录此用户(禁用密码)。配置 sudo 以允许此用户以 root 身份执行特定/脚本命令。
这会带来以下安全后果:
外部黑客无法通过暴力破解特定帐户的密码。
任何获得此帐户访问权限的人都只能执行单个脚本/命令。
其他用户不会通过这种构造获得提升的权限。
没有 setuid 弱点。