在Bash脚本中正确地回显变量

3

根据以下内容,我正在尝试在脚本中混淆密码。

在bash文件中隐藏/加密密码以防止意外查看

但是,因为这个密码中包含非字母数字字符,所以我认为"$MYPASS"变量在脚本倒数第二行无法正确输出。

我的脚本:

#!/bin/bash
PATH=/bin:/usr/bin:/sbin:/usr/sbin export PATH
MYENCPASS='IURv34bmNocv98RnZXQhCg=='
MYPASS=`echo "$MYENCPASS" | base64 --decode`

echo
echo Enter username you\'d like to change password for:
read USERNAME
dscl /LDAPv3/127.0.0.1 -read /Users/$USERNAME >/dev/null 2>&1

if [ "$?" != "0" ]; then

echo
echo -e "\033[31m Username $USERNAME does not exist! Exiting..."
echo -e "\033[0m"
exit 1
fi

echo
echo Enter New Password for "$USERNAME"
read PASSWORD
dscl -u diradmin -P "$MYPASS" /LDAPv3/127.0.0.1 passwd /Users/$USERNAME $PASSWORD
echo Password successfully changed for $USERNAME to $PASSWORD at `date` | tee -a /var/log/odpasswd.log

非常感谢您的想法和建议!

谢谢,丹

1个回答

3

首先,您需要引用参数以回显,以避免字符串拆分和全局扩展:

echo "Password successfully changed for $USERNAME to $PASSWORD at `date`"

其次,如果你想要以机器可解析的形式输出密码,请使用printf %q

printf 'Password successfully changed for %s to %q at %s\n' \
  "$USERNAME" "$PASSWORD" "$(date)"

顺便说一下--在本地变量中使用全大写名称是不好的做法(因为它可能会与内置和环境变量发生命名空间冲突)。


您的脚本完整版本,更加努力地遵循脚本编写的最佳实践(但仍然严重违反安全良好实践),看起来应该像这样:

#!/bin/bash

# you probably don't need to export PATH -- if something is already exported,
# it stays exported on updates.
PATH=/bin:/usr/bin:/sbin:/usr/sbin

## this is really, _really_ horrible "security".
myencpass='IURv34bmNocv98RnZXQhCg=='
mypass=$(base64 --decode <<<"$myencpass")

echo
echo "Enter username you'd like to change password for:"
read -r username
if ! dscl /LDAPv3/127.0.0.1 -read "/Users/$username" &>/dev/null; then
  # This is bad practice -- assuming that the only error that can happen is
  # the nonexistent-user case, and hiding any other error messages, means that
  # the user can't diagnose the _actual_ cause of any other error.
  printf '\n\033[31m Username %s does not exist! Exiting...\033[0m\n' "$username"
  exit 1
fi

printf '\nEnter New Password for %s\n' "$username"
read -r password
if dscl -u diradmin -P "$mypass" /LDAPv3/127.0.0.1 passwd "/Users/$username" "$password"; then
  # previously, there was no conditional here, so we logged that this was
  # successful even if it failed.
  # And, of course, storing users' plaintext passwords in a log makes you evil.
  printf "Password successfully changed for %s to %q at %s\n" \
    "$username" "$password" "$(date)" \
    | tee -a /var/log/odpasswd.log
fi

如果你想以正确的方式实现这个功能,而不是尝试这种混淆技术,你应该使用 LDAP 进行身份验证,并使用缓存的 Kerberos 令牌(我假设这是 MacOS 的 Open Directory - 它可以做到),仅由脚本运行用户可读,并使用 sudo 允许临时特权升级到能够在运行此脚本时读取令牌的用户。


嗨,查尔斯,感谢您的评论和建议,以及解决方案。但是这个脚本只是为一个管理人员而设计的,没有其他人使用,所以虽然它不是正确的方法,但它完全可以胜任,特别是在防火墙后面。如果您感到有兴趣,我也很想知道如何使用Kerberized方法!干杯,丹 - Dan
抱歉,Charles,你的脚本完美运行,只是它没有回显%s中的日期/时间。有什么修复的想法吗? - Dan
@Doug 噢,我忘记了日期调用。已经编辑添加了。至于Kerberized方法——自从我做过那件事以来已经过了很长时间,需要一些研究才能找回它。也许你可以把它作为一个单独的问题来问?(即使你不这样做,把混淆的密码放在一个权限受限的文件中,并要求使用此脚本的用户通过sudo跳转到它;如果你控制sudo授予的权限,你可以让他们运行脚本,但不让他们看到它读取的文件)。 - Charles Duffy
Charles,感谢你修复日期问题并提出使用单独密码文件的绝妙建议,我知道如何解决这个问题了。非常感谢! - Dan

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接