使用sudo,可以作为其他用户执行命令,真的安全地将参数传递给该命令。
示例讨厌的论点:
nastyArg='"double quoted" `whoami` $(whoami) '"'simple quoted "'$(whoami)'"'"
预期输出,通过termninal运行为congelli501:
% echo "$nastyArg"
"double quoted" `whoami` $(whoami) 'simple quoted $(whoami)'
通过sudo执行为congelli501:
# sudo -u congelli501 -- echo "$nastyArg"
"double quoted" `whoami` $(whoami) 'simple quoted $(whoami)'
执行为congelli501,通过su(通常的转义方法):
# su congelli501 -c "echo '$nastyArg'"
"double quoted" `whoami` $(whoami) simple quoted congelli501
正如您所看到的,该参数未被安全传递,因为它被shell重新解释。
有没有办法通过su启动命令并直接传递其参数,就像使用sudo一样?
答案 0 :(得分:1)
将命令作为su中的shell脚本参数传递似乎有效:
# su congelli501 -s "$(which echo)" -- "$nastyArg" "'another arg'"
"double quoted" `whoami` $(whoami) 'simple quoted $(whoami)' 'another arg'
使用示例:
# Safely execute a command as an other user, via su
#
# $1 -> username
# $2 -> program to run
# $3 .. n -> arguments
function execAs() {
user="$1"; shift
cmd="$1"; shift
su "$user" -s "$(which "$cmd")" -- "$@"
}
execAs congelli501 echo "$nastyArg" "'another arg'"
答案 1 :(得分:1)
这里的根本问题是你试图嵌套引号。您希望将su -c "stuff "with" double "quotes"
解析为|su|
,|-c|
,|stuff "with" double "quotes"|
,但它实际上会被解析为|su|
,|-c|
,{{1 }},|stuff |
,|with|
,| double|
但是最后四个标记在评估后粘贴在一起作为一个字符串(请注意"内部"引号终止的空格表面上的"外部"引用而不是包裹在其中。)
在双引号内,{<1}}在任何内容传递给|quotes|
之前由shell 扩展。
你可以做的是(a)在`whoami`
(几乎注定失败)或(b)定义的值周围添加更多引号它在su
执行的shell的上下文中。另一个不同的选择是(c)以一种解除它的方式传递值,例如在标准输入上。
$nastyArg
这可能看起来过于简单化了,但是当你对su
以某种方式可能评估的内容没有完全信任时,这真的是可行的方法。
这是printf '%s\n' "$nastyArg" | su -c 'cat' congelli501
优于root
的原因之一。