【问题标题】:expect doesn't pass input to passwd in bash script期望不会在bash脚本中将输入传递给passwd
【发布时间】:2016-07-27 07:28:12
【问题描述】:

我正在尝试使用 expect 将 $PASSWORD 变量内容传递到 passwd。这似乎可以添加用户,但是一旦您尝试使用其中一个用户通过 ssh 登录,它就不起作用了。如果我手动设置密码,那就没问题了。

以前有人遇到过这个问题吗?

USERS=(user1 user2 user3)



generatePassword ()
{
        pwgen 16 -N 1
}

# Check if user is root
if [ $(whoami) != 'root' ]; then
        echo "Must be root to run $0"
        exit 1;
fi

# Check if pwgen is installed:
if [[ $(dpkg -s pwgen > /dev/null 2>&1; echo ${PIPESTATUS} ) != '0' ]]; then
        echo -e "pwgen is not installed, this script will not work without it\n\n'apt-get install pwgen'\n"
        exit 1;
    else
        echo -e "Starting Script...\n\n"
fi

# Iterate through users and add them with a password
for i in ${USERS[@]}; do
        PASSWORD=$(generatePassword)
        echo "$i $PASSWORD" >> passwords

        useradd -m "${i}"

        echo -e "Adding $i with a password of '$PASSWORD'\n"

        expect -c "
            spawn passwd ${i}

            expect \"Enter new UNIX password:\"
            send -- \"$PASSWORD\r\"
            send -- \"\r\"
            expect \"Retype new UNIX password:\"
            send -- \"$PASSWORD\r\"
            send -- \"\r\"
             "
            echo -e "\nADDED $i with a password of '$PASSWORD'\n"
done

【问题讨论】:

  • Ewww。您正在对希望解析为代码的内容执行字符串替换?这是一种严重的代码异味——如果允许用户设置自己的密码,这可能会被用作任意命令注入漏洞。
  • 顺便说一句,请参阅pubs.opengroup.org/onlinepubs/9699919799/basedefs/… 以了解围绕环境变量名称(以及共享命名空间的 shell 变量的名称)的 POSIX 约定——全大写名称由对 shell 或有意义的变量使用操作系统,至少有一个小写字符的名称保留给应用程序使用;因此,请考虑password 而不是PASSWORD,以避免错误地覆盖对操作系统有意义的变量。
  • @CharlesDuffy - 我知道,这是一个小时无知摸索的结果!我正在努力变得更好
  • 顺便说一句——考虑养成使用printf 而不是echo -e 的习惯。请参阅echo 的 POSIX 标准,特别是 APPLICATION USAGE 部分,pubs.opengroup.org/onlinepubs/009604599/utilities/echo.html -- bash 通过实现 @987654329 实际上是 noncompliant (不仅扩展了标准,而且违反了黑字行为) @ 默认情况下,并且使用一些非默认 shell 选项(例如 xpg_echo),该行为会消失(并且 echo -e 在输出上打印 -e)。
  • 谢谢!将用 printf 修改我的脚本

标签: bash debian expect passwd


【解决方案1】:

您根本不需要期望:使用chpasswd 而不是passwd

#!/bin/bash
users=(user1 user2 user3)

# Check if user is root
if [[ "$(id -un)" != 'root' ]]; then
    echo "Must be root to run $0"
    exit 1
fi

# Check if pwgen is installed:
if ! dpkg -s pwgen > /dev/null 2>&1; then
    printf "pwgen is not installed, this script will not work without it\n\n'apt-get install pwgen'\n"
    exit 1
else
    printf "Starting Script...\n\n"
fi

# Iterate through users and create a password
passwords=()
for user in "${users[@]}"; do
    useradd -m "$user"
    password="$user:$(pwgen 16 -N 1)"
    passwords+=("$password")
    echo "Adding user '$user' with '$password'"
done 

printf "%s\n" "${passwords[@]}" | chpasswd

我添加了几个必需的引号。
我已经简化了 dpkg 检查。

或者,也许更简单,newusers 以原子方式执行“useradd”和“passwd”功能。

for user in "${users[@]}"; do
    password="$user:$(pwgen 16 -N 1)"
    password=${password//:/-}         # replace all colon with hyphen
    printf "%s:%s::::/home/%s:/bin/bash\n" "$user" "${password//:/-}" "$user"
done | newusers

我认为 newusers 不会从 /etc/skel 填充主目录。

【讨论】:

    【解决方案2】:

    首先:最直接的问题是当你输入\r 时你没有转义反斜杠文字,所以这些只是在expect 一侧更改为rs;似乎可以解决问题的最小可能更改是将其更改为\\r


    但是——不要那样做:在expect 中,与其他语言一样,字符串应该作为文字传递,而不是替换到代码中。

    expect -f <(printf '%s\n' '
    set username [lindex $argv 0];
    set password [lindex $argv 1];
    spawn passwd $username
    
    expect "Enter new UNIX password:"
    send -- "$password\r"
    send -- "\r"
    expect "Retype new UNIX password:"
    send -- "$password\r"
    send -- "\r"
    ') -- "$i" "$PASSWORD"
    

    您还可以将有问题的文字文本保存到文件中,然后运行 ​​expect -f passwd.expect -- "$i" "$PASSWORD",这同样有效(并且避免依赖 &lt;() 语法,这是 bash 采用的 ksh 扩展)。

    【讨论】:

    • 我可能会以 Un expect 的方式使用 Expect... 我是否正确假设我需要 [lindex $argv 0] 部分?如果我在脚本开头使用参数,我认为这是需要的?
    • 所以,回复:[lindex $argv 0] 部分,所做的是将变量从命令行拉到 awk 中。 (见最后,-- 之后,我们将 shell 变量放在 awk 命令行上;set usernameset password 是我们获取这些命令行参数并为它们创建 awk 变量的地方) .
    • 这样做的目的是避免通过令人惊讶或恶意的用户名或密码进行注入攻击,而不是将值直接替换到 awk 脚本中。请参阅xkcd.com/327 快速介绍 SQL 等效的攻击,从而保护您免受攻击;防止数据将内容注入代码的最佳方法是将数据从代码带外传递,这里就是这样做的。
    猜你喜欢
    • 2017-06-20
    • 2020-11-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-09-02
    • 2016-02-28
    • 1970-01-01
    • 2014-12-16
    相关资源
    最近更新 更多