【问题标题】:How to provide password to a command that prompts for one in bash?如何为在 bash 中提示输入密码的命令提供密码?
【发布时间】:2011-06-18 23:11:28
【问题描述】:

我正在编写一个 UNIX shell 函数,它将执行一个提示用户输入密码的命令。我想将密码硬编码到脚本中并将其提供给命令。我试过将密码输入到这样的命令中:

function() {
    echo "password" | command
}

这可能不适用于某些命令,因为该命令可能会在提示输入密码之前刷新输入缓冲区。

我也尝试将标准输入重定向到包含这样密码的文件,但这也不起作用:

function() {
    echo "password" > pass.tmp
    command < pass.tmp
    rm pass.tmp
}

我知道有些命令允许将密码作为参数提供,但我宁愿通过标准输入。

我正在寻找一种快速而肮脏的方式将密码输入到 bash 中的命令中。

【问题讨论】:

  • 你看过autoexpect 吗?没有比这更容易的了。您只需将命令传递给它,它就会记录您所做的一切并为您创建期望文件。

标签: bash unix passwords


【解决方案1】:

如何使用 autoexpect 将密码输入命令:

这些步骤以 Ubuntu 12.10 桌面进行说明。您的发行版的确切命令可能略有不同。

这很危险,因为您有可能将您使用的任何密码暴露给任何可以读取自动预期脚本文件的人。

不要像这样通过管道传递您的 root 密码或超级用户密码。 Root 工具包会立即找到它,并且您的盒子已归您所有。

EXPECT 生成一个进程,读取进来的文本,然后发送脚本文件中预定义的文本。

  1. 确保您已安装 expectautoexpect

    sudo apt-get install expect
    sudo apt-get install expect-dev
    
  2. 仔细阅读:

    man expect
    man autoexpect
    
  3. 转到您的主目录:

    cd /home/el
    
  4. 用户el无法将文件chown到root,必须输入密码:

    touch testfile.txt
    sudo chown root:root testfile.txt 
       [enter password to authorize the changing of the owner]
    
  5. 这是我们想要自动化的密码输入。重新启动终端以确保 sudo 再次要求我们输入密码。再次转到 /home/el 并执行以下操作:

    touch myfile.txt
    
    autoexpect -f my_test_expect.exp sudo chown root:root myfile.txt
    
        [enter password which authorizes the chown to root]
    
    autoexpect done, file is my_test_expect.exp
    
  6. 您已创建my_test_expect.exp 文件。您的超级机密密码以明文形式存储在此文件中。这应该让你非常不舒服。通过尽可能地限制权限和所有权来减轻一些不适:

    sudo chown el my_test_expect.exp     //make el the owner.
    sudo chmod 700 my_test_expect.exp    //make file only readable by el.
    
  7. 你会在my_test_expect.exp的底部看到这些命令:

    set timeout -1
    spawn sudo chown root:root myfile.txt
    match_max 100000
    expect -exact "\[sudo\] password for el: "
    send -- "YourPasswordStoredInPlaintext\r"
    expect eof
    
  8. 您需要验证上述期望命令是否合适。如果 autoexpect 脚本过于敏感或不够敏感,那么它将挂起。在这种情况下,这是可以接受的,因为 expect 正在等待总是会到达的文本。

  9. 以用户 el: 运行期望脚本:

    expect my_test_expect.exp 
    spawn sudo chown root:root myfile.txt
    [sudo] password for el: 
    
  10. my_test_expect.exp 中包含的密码由用户 el 通过管道传输到 root 的 chown。要查看密码是否被接受,请查看myfile.txt

    ls -l
    -rw-r--r--  1 root root          0 Dec  2 14:48 myfile.txt
    

因为它是 root 用户,并且 el 从未输入过密码,所以它起作用了。如果您使用此脚本公开您的 root、sudo 或超级用户密码,那么在您的机器上获取 root 将很容易。这就是让每个人都毫无疑问的安全系统的惩罚。

【讨论】:

  • 这篇文章不应该像现在这样被点赞。密码是有原因的,而这在很大程度上违背了这个目的。
  • 屏幕刮板和机器人多肉手指戳 macbook 触控板以证明我们不是机器人;尽管如此,在 bash 中传递密码明文是最糟糕的代码气味,当我在 2013 年写这篇文章时,有人发明了一台时间机器并击中了我的头。
【解决方案2】:

看看autoexpect(不错的教程HERE)。在不使用诡计的情况下,它会尽可能地快速而肮脏。

【讨论】:

  • 太棒了 - 看到我的真正意图是能够做一些快速而肮脏的事情,这正是我所需要的!
  • 让我在可悲实现的 VPN 中输入了三次相同的密码。 (我还创建了一个只运行 expect vpn.sh 的脚本)
  • 在这里的答案中至少包含一个快速的 sn-p 会很棒。六年后,链接并不总是有效。这个可以,但是:)
  • @Unsigned 更新了链接以确保它会持续很长时间。不完全是您正在寻找的东西,但 Eric 的回答让您到达那里。
【解决方案3】:

您可以使用-S 标志从标准输入中读取。在下面找到一个示例:

function shutd()
{
  echo "mySuperSecurePassword" | sudo -S shutdown -h now
}    

【讨论】:

  • 非常感谢。这可以完美地作为一个快速而肮脏的香草实现。
  • 如果我有一个提示输入密码的命令run this_command,你会如何改变这个功能?
  • @AwaisKaleem 这个答案应该澄清它只适用于像shutdown 这样导致系统特别提示输入sudo 密码的命令。通过首先通过sudo 选项-S 获得超级用户权限,这可以避免调用shutdown 来询问密码。它不适用于本身提示输入密码的命令。
【解决方案4】:

安全命令不允许这样做,而且恐怕是正确的 - 这是一个您可以驾驶卡车穿过的安全漏洞。

如果您的命令不允许使用输入重定向、命令行参数或配置文件,那么您将不得不诉诸严重的诡计。

某些应用程序实际上会打开/dev/tty,以确保您很难克服安全问题。您可以通过暂时接管/dev/tty(例如,创建自己的管道)来绕过它们,但这需要严格的权限,甚至也可能被击败。

【讨论】:

  • 你说得对,我理解为什么这是一个安全漏洞,但我已经在一个安全的环境中,所以我主要关心的是一些快速且肮脏的东西,而不必诉诸严重的诡计。感谢您的回复!
【解决方案5】:

read

这是一个使用read 获取密码并将其存储在变量pass 中的示例。然后,7z 使用密码创建加密存档:

read -s -p "Enter password: " pass && 7z a archive.zip a_file -p"$pass"; unset pass

但要注意密码可以easily be sniffed

【讨论】:

  • 这种方法只适用于像7z这样允许命令行输入密码的命令,并且特别要求避免这种方法的问题,因为它可能会在shell历史记录中留下密码并暴露于ps,所以它比这里的其他答案差得多。
【解决方案6】:

提示输入密码的程序通常将 tty 设置为“原始”模式,并直接从 tty 读取输入。如果你在 pty 中生成子进程,你可以让它工作。这就是 Expect 所做的......

【讨论】:

  • 你能举个简单的例子吗?
【解决方案7】:

只需使用:

echo "password" | sudo -S mount -t vfat /dev/sda1 /media/usb/;
if [ $? -eq 0 ]; then
    echo -e '[ ok ] Usb key mounted'
else
    echo -e '[warn] The USB key is not mounted'
fi

这段代码对我有用,它在 /etc/init.d/myscriptbash.sh 中

【讨论】:

    【解决方案8】:

    这是一个非常不安全的想法,但是: Using the passwd command from within a shell script

    【讨论】:

    • 我不认为 OP 只是在询问passwd