命令行中的这些行解释了我的用例:
应谨慎使用命令行参数中的通配符。因为命令行参数作为单个连接字符串进行匹配,所以通配符(例如“?”)或 '*' 可以匹配多个单词。例如,当 sudoers 条目如下:
%operator ALL = /bin/cat /var/log/messages* will allow command like: $ sudo cat /var/log/messages.1 It will also allow: $ sudo cat /var/log/messages /etc/shadow
这可能不是我们想要的。
如何让操作员看到所有以 开头的文件/var/log/messages
?
文件名中不会出现空格。
我希望*
像 PCRE 那样行事\S*
更新
由于sudo
不支持正则表达式,我在这里创建了一个新问题:https://softwarerecs.stackexchange.com/questions/65887/sudo-alternative-which-supports-pcre
上面的例子来自man sudoers
. “命令行参数中的通配符应谨慎使用”部分。
答案1
sudoers 语法没有提供出路,我可能建议编写一个包装器脚本(例如,忽略除第一个参数之外的所有内容,并使用realpath
) 和朋友对其进行规范化),但无论如何它都没有用:
sudo cat /var/log/messages/../../../etc/shadow
在不知道您的实际用例的情况下,我只能对联机帮助页中的示例进行评论,为此我想说实际的解决方案是根本不使用 sudo,而是使用 ACL。使用 ACL 授予用户对目录中所有内容的访问权限,文件系统将负责限制他们的访问权限。
答案2
对于你的情况,我认为你能得到的最接近的是:
%operator ALL = /bin/cat /var/log/messages*, !/bin/cat /var/log/messages*\ *
首先,/bin/cat
仅当它具有任何以 开头的“参数字符串”时才允许/var/log/messages
,然后如果它在任何点上有空格,则禁止相同的“参数字符串”。
这实际上禁止了 的多个参数cat
,但是基于“整个字符串”的基础,它不允许的参数sudo cat /var/log/messages /var/log/messages.1
与它不允许的参数一样多sudo cat /var/log/messages /etc/shadow
。而且,它不允许合法的文件名有空格,例如假设的/var/log/messages-with-' '-space
文件。
答案3
我的首选是自定义脚本,/usr/local/bin/cat-messages
用于在外部执行验证sudoers
:
#!/bin/bash
#
args=()
prefix='/var/log/messages'
for arg in "$@"
do
# Canonicalise
real=$(readlink -f "$arg")
# Check it is a real file matching the prefix
if [[ "$real" =~ ^"$prefix" ]] && [[ -f "$real" ]]
then
args+=("$arg")
else
echo "WARNING: skipping $arg" >&2
fi
done
cat "${args[@]}"
您可以将其添加到sudoers
类似这样的行
%operator ALL = NOPASSWD: /usr/local/bin/cat-messages
并且(假设/usr/local/bin
在你的中PATH
)这样称呼它
sudo cat-messages /var/log/messages.1 /var/log/messages
实际上,由于它是一个 shell 脚本,因此您几乎可以让它使用 来调用自身sudo
,从而使用户的生活变得更简单。 (这里不存在安全问题,因为sudo
仍然只会考虑/usr/local/bin/cat-messages
。)
#!/bin/bash
#
[[ $(id -u) != 0 ]] && exec sudo "$0" "$@"
args=()
prefix='/var/log/messages'
... as before ...
你可以像这样简单地调用这个变体
cat-messages /var/log/messages.1 /var/log/messages
或者
cat-messages /var/log/messages*