I've seen in more than one discussion that using echo to pipe to passwd is dangerous because one can get arguments provided to echo from process list.
I'm currently working on a tool, that changes passwords remotely via ssh. I do use echo method because I do not have root access to use usermod or chpasswd.
cmd:
echo -e 'old\nnew\nnew' | passwd
To check how easy it is - I tried. But could not get them.
this was my method:
#!/bin/bash
filename=$1
while true
do
    echo "$(pgrep -af passwd)" >> "$filename"
    sleep 0.1
done
I few times changed password via echo but could not seen anything. I think that sleep 0.1 may be a problem.
How easy it is to get it from process list and therefore how insecure it is to use it this way.
 
                        
It depends on whether the shell you're using has
echoas a builtin, or uses an external binary (/bin/echo). If it's an external binary, it'll be run as a subprocess with the password plainly visible in its argument list (viaps,pgrep, etc). If it's a builtin, anechocommand in a pipeline will run as a subprocess, but it'll be a subshell with the same visible argument list as the parent shell (i.e. it's safe).So it's probably safe, but there are several complications to worry about. First, if you're running this on a remote computer via
ssh, you don't necessarily know what its default shell is. If it's bash, you're ok. If it's dash, I think you have a problem. Second, you don't just have to worry about the remote shell and/orechocommand, you have to worry about every step along the path from your local script to that remoteechocommand. For example, if you use:...then the remote
echois probably safe (depending on the remote shell), but as @thatotherguy pointed out the password will be visible in both the remote shell's (bash -c echo -e 'foo\nbar\nbar' | passwd) and in the localsshprocess's argument list.There's another complication, BTW:
echoisn't consistent about how it handles options (like-e) and escapes in the output string (see this question for an example). You're much better off usingprintf(e.g.printf '%s\n' "$oldpass" "$newpass" "$newpass"), which is also a builtin in bash. Or, if you're sure you're using bash, you can use here-string (<<<string) instead. It doesn't interpret escapes at all, but you can use bash's$' 'construct to interpret them:This doesn't involve a subprocess at all (either
/bin/echoor a subshell), so no worries about the process table.Another possibility to avoid both the problems of uncertain remote shells and the password showing up in
ssh's argument list is to pass the passwords viassh's stdin: