我在多个讨论中看到使用echo to pipe to passwd是危险的,因为可以从进程列表中获取提供的参数。
我目前正在开发一种通过ssh远程更改密码的工具。我使用echo方法,因为我没有root访问权限来使用usermod或chpasswd。
CMD:
echo -e 'old\nnew\nnew' | passwd
要检查它有多容易 - 我试过了。但无法得到它们。
这是我的方法:
#!/bin/bash
filename=$1
while true
do
echo "$(pgrep -af passwd)" >> "$filename"
sleep 0.1
done
我几次通过echo更改了密码,却看不到任何东西。我认为 sleep 0.1 可能是个问题。
从流程列表中获取它是多么容易,因此以这种方式使用它是多么不安全。
答案 0 :(得分:3)
如果您通过echo|passwd
调用ssh
命令,例如:
client$ ssh example.com "echo -e 'foo\nbar\nbar' | passwd"
然后您需要查看的进程不是passwd
,而是远程端sshd
调用的用户登录shell:
server$ until pgrep -af bash | grep passwd; do true; done
8387 bash -c echo -e 'foo\nbar\nbar' | passwd
答案 1 :(得分:2)
这取决于您使用的shell是echo
作为内置函数,还是使用外部二进制文件(/ bin / echo)。如果它是外部二进制文件,它将作为子进程运行,密码在其参数列表中明显可见(通过ps
,pgrep
等)。如果它是内置的,管道中的echo
命令将作为子进程运行,但它将是一个子shell,它具有与父shell相同的可见参数列表(即它是安全的)。
所以可能安全,但有几个并发症需要担心。首先,如果您通过ssh
在远程计算机上运行它,则不一定知道它的默认shell是什么。如果它是bash,你没问题。如果它破折号,我认为你有问题。其次,您不必担心远程shell和/或echo
命令,您必须担心从本地脚本到远程echo
命令的路径中的每一步。例如,如果您使用:
ssh user@computer "echo -e 'old\nnew\nnew' | passwd"
...然后远程echo
可能是安全的(取决于远程shell),但是@thatotherguy指出密码将在远程shell(bash -c echo -e 'foo\nbar\nbar' | passwd
)和在本地ssh
进程的参数列表中。
还有另一个复杂问题,BTW:echo
关于它如何处理选项(如-e
)和输出字符串中的转义不一致(例如,参见this question)。你最好使用printf
(例如printf '%s\n' "$oldpass" "$newpass" "$newpass"
),这也是bash内置的。或者,如果您确定要使用bash,则可以使用here-string(<<<string
)代替。它根本不解释转义,但您可以使用bash的$' '
构造来解释它们:
passwd <<<"$old"$'\n'"$new"$'\n'"$new"
这根本不涉及子进程(/bin/echo
或子shell),所以不用担心进程表。
另一种避免远程shell不确定和ssh
参数列表中出现的密码问题的可能性是通过ssh
的stdin传递密码:
ssh user@computer passwd <<<"$old"$'\n'"$new"$'\n'"$new"