没有评估的Tilde扩展

时间:2016-06-26 01:02:21

标签: bash

我需要获取用户主文件夹。目前我正在使用此

home=$(eval echo ~$user)

调用者提供$user的内容,因此不受信任值。在这里使用eval危险吗?如果是(可能),如何在没有它的情况下解决它?

2 个答案:

答案 0 :(得分:4)

在拥有它的系统上,您可以使用getent(1)

$ getent passwd "$username" | cut -d: -f 6
/path/to/user/home

确保检查空结果。

答案 1 :(得分:1)

在解析过程中很早就发生了Tilde扩展,没有多次评估就没有办法实现你想要的东西。因此eval 的解决方案。实现您想要的最安全的方法是:

eval "$(printf "home=~%q" "$user")"

感谢%q修饰符,扩展$user将被完全引用,因此这里没有危险(不要修改该行,但是你会这样做)肯定会引入一些安全漏洞)。

你不应该单独使用它:在这一行之后,你必须检查你是否有一个有效的目录,例如,

if [[ ! -d $home ]]; then
    echo >&2 "Couldn't find home dir for user $user"
    exit 1
fi

还要考虑user为空的情况:在这种情况下,home将是运行脚本的用户的主目录。您是否想要此行为取决于您。

还需要考虑另一点:当user包含斜杠时:您是否想要此功能取决于您。

现在,根据您希望拥有的功能,可以更好地针对某些预定义模式验证扩展$user,例如,

if [[ $user != [a-z]*([-a-z0-9_]) ]]; then
    echo >&2 'Provided user doesn't match valid pattern'
    exit 1
fi

事实证明,通过此验证,您的解决方案是安全的。

示例:

一切运作良好的情况:

$ user=gniourf
$ eval "$(printf "home=~%q" "$user")"
$ declare -p home
declare -- home="/home/gniourf"

对您的代码造成危险的情况(代码ls将被执行,但不会在此处执行):

$ user='; ls >&2'
$ eval "$(printf "home=~%q" "$user")"
$ declare -p home
declare -- home="~; ls >&2"