我在不止一次的讨论中看到,使用echo管道连接到passwd是危险的,因为可以从进程列表中获得提供给echo的参数。
我目前正在开发一个工具,它可以通过ssh远程更改密码。我确实使用了echo方法,因为我没有使用usermod或chpasswd的root访问权限。
cmd:
echo -e 'oldnnewnnew' | passwd
为了检查它有多容易,我试过了。但无法得到它们。
这是我的方法:
#!/bin/bash
filename=$1
while true
do
echo "$(pgrep -af passwd)" >> "$filename"
sleep 0.1
done
我通过echo更改了几次密码,但什么都看不见。我认为睡眠0.1可能是个问题。
从进程列表中获取它是多么容易,因此以这种方式使用它是多么不安全。
这取决于您使用的shell是将echo
作为内置,还是使用外部二进制(/bin/echo)。如果它是一个外部二进制文件,它将作为一个子进程运行,密码在其参数列表中清晰可见(通过ps
、pgrep
等)。如果它是内置的,管道中的echo
命令将作为子进程运行,但它将是一个子shell,具有与父shell相同的可见参数列表(即它是安全的)。
因此,可能是安全的,但有几个并发症需要担心。首先,如果你通过ssh
在远程计算机上运行它,你不一定知道它的默认外壳是什么。如果是bash,你就可以了。如果是dash,我认为你有问题。其次,您不仅需要担心远程shell和/或echo
命令,还需要担心从本地脚本到远程echo
命令的每一步。例如,如果您使用:
ssh user@computer "echo -e 'oldnnewnnew' | passwd"
则远程echo
可能是安全的(取决于远程shell),但正如@thathotherguy所指出的,密码将在本地ssh
进程的参数列表中的远程shell(bash -c echo -e 'foonbarnbar' | passwd
)和中都可见。
还有另一个复杂的问题,BTW:echo
在如何处理选项(如-e
)和输出字符串中的转义方面不一致(有关示例,请参阅此问题)。您最好使用printf
(例如printf '%sn' "$oldpass" "$newpass" "$newpass"
),它也是bash中的内置程序。或者,如果您确定使用的是bash,则可以使用here字符串(<<<string
)。它根本不解释转义,但您可以使用bash的$' '
构造来解释它们:
passwd <<<"$old"$'n'"$new"$'n'"$new"
这根本不涉及子流程(/bin/echo
或子shell),因此无需担心流程表。
避免不确定的远程shell和密码出现在ssh
的参数列表中的问题的另一种可能性是通过ssh
的stdin:传递密码
ssh user@computer passwd <<<"$old"$'n'"$new"$'n'"$new"
如果要通过ssh
调用echo|passwd
命令,例如:
client$ ssh example.com "echo -e 'foonbarnbar' | passwd"
那么您需要查看的进程不是passwd
,而是远程端sshd
调用的用户登录shell:
server$ until pgrep -af bash | grep passwd; do true; done
8387 bash -c echo -e 'foonbarnbar' | passwd