将包含 $!@`' 等特殊字符的密码读取到 Bash 脚本中的最佳实践

将包含 $!@`' 等特殊字符的密码读取到 Bash 脚本中的最佳实践

stdin我正在尝试从Bash 脚本中的变量中读取密码。然后应将该变量扩展为 ssh 命令并传输到服务器。在那里,密码应该以正确转义的方式到达,因此它可以用作另一个命令的输入。 (在本例中更改我的 pihole 的登录密码)。

目前我有类似的东西:

read -rs -p "Password: `echo $'\n> '`" newpass
ssh root@gate "pihole -a -p \"${newpass}\""

但也尝试过:

ssh root@gate "pihole -a -p ""'""${newpass}""'"
ssh root@gate 'pihole -a -p '"${newpass}"
ssh root@gate 'pihole -a -p '"${newpass}"''
ssh root@gate "pihole -a -p \'${newpass}\'"
ssh root@gate 'pihole -a -p ''\''"${newpass}"'\''

即使使用 printf:

IFS= read -rs -p "Password: `echo $'\n> '`" newpass
command=$(printf 'pihole -a -p %s\n' "$newpass")

或者

IFS= read -rs -p "Password: `echo $'\n> '`" newpass
command=$(printf 'pihole -a -p '\''%s'\''\n' "$newpass")

还有很多。但有了这个密码:a$#5!6k?h'v;z'他们都失败了。而且里面甚至还没有反勾号……

我向所有 Bash 专家提出的问题是:

将密码解析为变量(用户可以在其中输入)的正确方法是什么字面上任何特点?

这包括:

$ 
!
` (backtick)
' (single quote)
"
;
#
@
\
/
~
\n

等等...

我已阅读此处和其他论坛中的所有相关问题,但找不到此用例的解决方案。

我知道,会有人建议使用 Python 或 C 或其他东西,但我仍然对 Bash 的功能感兴趣。

但是,如果使用 Bash 绝对不可能完成此任务,那么我也对如何使用其他工具(干净且安全地)完成此任务的想法感兴趣。

提前致谢

答案1

几种可能的解决方案。

  • 让 pihole 直接询问密码,而不是使用您自己的提示符。

    ssh -t user@host pihole -a -p
    
  • read在目标端运行您自己的提示符:

    ssh -t user@host 'read -rsp "Password: " newpass && pihole -a -p "$newpass"'
    
  • 将其通过管道:

    echo "$newpass" | ssh user@host 'read -r newpass && pihole -a -p "$newpass"'
    
  • 引用您在传递之前读取的密码:

    read -rsp "Password: " newpass
    qnewpass=$(printf "%q" "$newpass")
    ssh user@host pihole -a -p "$qnewpass"
    
  • 对密码进行编码并在另一侧对其进行解码:

    newpass_base64=$(printf "%s" "$newpass" | base64)
    ssh user@host "pihole -a -p \$(echo $newpass_base64 | base64 -d)"
    
  • 根本不要使用特殊字符,XKCD风格。 ;-)

答案2

$ echo "$pw"
$!@`',

$ echo "${pw@Q}"
'$!@`'\'','

应该可以做到这一点。但我不知道bash这是在哪个版本中引入的。这也有效,并且可能更早可用:

$ printf %q "$pw"
\$\!@\`\'\,
# or, avoiding the command substitution
$ printf -v pw_ql1 %q "$pw"
$ echo "$pw_ql1"

相关内容