我正在使用下面的 bash 脚本来测试sudo
远程主机上是否可用。
我从用户输入中获取密码。我理解(在一定程度上)在脚本中使用密码会涉及安全性权衡,所以我对此的某个方面有疑问。
请参阅下面的脚本,该脚本使用sshpass
并测试用户是否能够sudo --stdin --validate
成功运行。
为了尽量避免泄露密码(据我所知?),我选择使用sshpass
with-e
而不是-p
,但只是想知道第二部分---该echo \"${SSHPASS}\" | sudo --stdin --validate
行。
运行此脚本并在远程主机上查看后history
,我无法在用户帐户或 root 帐户的命令行上看到“回显”的密码。
所以我的问题是:在远程端进行这样的回显是否会在任何地方暴露密码(如果是,在哪里?),或者下面这种方法是否“相当安全”?
两端的用户环境都是Ubuntu 18或者20。
#!/bin/bash
# obtain username and host from user input
read -p "Enter username@host: " remote
# obtain password from user input
read -r -s -p "Enter password: " SSHPASS
# set password as environment variable for `sshpass` below, it requires this for `-e`
export SSHPASS
echo
echo -n "Testing if can sudo on ${remote}... "
if result=$( sshpass -e ssh -o PasswordAuthentication=yes "${remote}" "echo \"${SSHPASS}\" | sudo --stdin --validate" 2>&1 ); then
echo "YES!"
else
echo "FAILED"
echo "${result}"
fi
unset SSHPASS
答案1
虽然看起来不像,但密码实际上已经暴露在本地和远程服务器上。
两种情况下的原因是它是进程的命令行的一部分,sshpass
或者更隐含的bash -c
,如下所述。
当您通过 运行命令时ssh <host> <command>
,命令部分通过 传递给登录 shell -c
。这意味着任何能够列出进程的用户都可以看到bash -c "echo "<password>" | sudo --stdin --validate"
。
如果您想测试一下,while ! ps aux | grep '[s]udo'; do :; done
只需像远程系统中的任何其他用户一样简单操作即可。请注意,这是一个主动等待循环,会导致 CPU 使用率激增。
为了解决这个问题,您应该回显密码并将其传送到您的 SSH,而不是远程回显:echo "${SSHPASS}" | sshpass -e ssh -o PasswordAuthentication=yes "${remote}" "sudo --stdin --validate" 2>&1
。
答案2
使用 GPG 加密和 PIPE 直接限制暴露,而不是将其输出到纯文本文件/字符串:
gpg -d -q .sshpasswd.gpg | sshpass -P 通过 ssh -i ~/.ssh/key.pem -ttR xxx.xxx.xxx.xxx
-P 传递
选项搜索例如“密码......”或“密码短语”提示来填写。
答案3
尝试在本地运行 sshpass(用于远程 sudo),但失败了
1. 测试
没有 ssh 的 sudo //ok
$ SSHPASS=your_passwd sshpass -e sudo id
uid=0(root) gid=0(root) groups=0(root)
sudo 和 ssh //失败
SSHPASS=your_passwd sshpass -v -e ssh localhost -t 'sudo id'
[sudo] password for xxx:
2. 原因
$ ssh root@localhost >/dev/null
root@localhost's password:
$ sudo id >/dev/null
[sudo] password for xxx:
$ ssh -t localhost sudo id
[sudo] password for xxx:
$ ssh -t localhost sudo id >/dev/null
//nothing
'sshpass' 无法通过 ssh + sudo 工作的原因是:正常sudo
或ssh
发送提示符到 tty,但ssh
+sudo
发送提示符到 stdout,但 sshpass 在 tty 等待提示符。
我猜测拓扑结构如下:
[local pty] <---> ssh <--(stdio)--> [remote pty] <---> sudo
解决方法
所以sudo --stdin
是简单的方法://在本地回显以确保安全
echo your_pass | ssh localhost 'sudo --stdin id'
或 //在远程运行 sshpass
$ ssh localhost 'SSHPASS=your_pass sshpass -e sudo id'
我记得bash只记录交互模式下执行的命令历史记录,
而以空格开头的cmd也不会记录:(ls 1
记录)vs ls 2
(不记录)