如何防止 sudo 用户运行特定命令?

she*_*har 31 linux sudo

我有一个非常敏感的网络设置,我真的不想弄乱它。我的网络由一群拥有 sudo 权限的用户组成。

我想阻止他们跑

service NetworkManager restart
service network restart
Run Code Online (Sandbox Code Playgroud)

命令。

有什么办法可以实现这一目标吗?

joe*_*dle 51

使用 CmndAliasALL永远不会安全

有 1000 种service network restart无需做就可以跑步的方法sudo service network restart。以下是顽皮用户可能会尝试的示例:

$ echo "service network restart" > /tmp/hax
$ chmod a+x /tmp/hax
$ sudo /tmp/hax
Run Code Online (Sandbox Code Playgroud)

如果您为用户提供ALL命令别名,然后尝试创建黑名单,他们将始终能够找到解决方法。黑名单 bash,他们将使用 python。黑名单 python,他们将使用 Perl。将 Perl 列入黑名单,他们将使用 PHP。没有人想要那个!

如果你真的不想别人去做什么事情,你应该做的是托马斯说,创造的东西,他们的白名单允许这样做。


设置白名单异常

可以在 底部附近找到一个带有排除项的小白名单示例man sudoers

 pete           HPPA = /usr/bin/passwd [A-Za-z]*, !/usr/bin/passwd root

The user pete is allowed to change anyone's password except for root on the HPPA
machines.  Note that this assumes passwd(1) does not take multiple user names
on the command line.
Run Code Online (Sandbox Code Playgroud)

(实际上,手册页中的这个示例是不安全的,可以被利用来更改 root 的密码!有关方法,请参阅下面的评论。)

我们可以尝试根据您的情况调整它,将所有service命令提供给员工组,但排除service network您有关的命令:

%staff ALL =   /usr/sbin/service *,                            \
             ! /usr/sbin/service *network*,                    \
             ! /usr/sbin/service *NetworkManager*
Run Code Online (Sandbox Code Playgroud)

ALL那个位置指的是 Host_Alias,而不是 Cmnd_Alias - 不是很混乱吗?)

用户将无法运行sudo bashorsudo teesudo wgetor sudo /path/to/malicious_script。如果您小心,您可以为您的用户将更多管理命令列入白名单。只是要具体!

注意:我*network上面的单词之前添加了,以防service将来在该工具中添加无害标志。假设--verbose将来添加了一个标志,那么用户将能够运行以下命令:

$ sudo service --verbose network restart
Run Code Online (Sandbox Code Playgroud)

所以我们需要*在服务名称之前使用任何标志。一个缺点是,这可能会阻止您实际上不介意用户运行的其他服务,例如调用safe-networknetwork-monitor也会被拒绝的服务。


让用户使用组权限编辑文件

您可以在下面找到使用rnanothroughsudo来让用户编辑一个或多个文件的各种尝试。但实际上,它们比应有的更复杂、更危险。

一个更简单、更安全的解决方案是更改要为其打开编辑权限的特定文件的组权限。下面是几个例子:

### Give steve the ability to edit his nginx config:
$ chgrp steve /etc/nginx/sites-available/steves_dodgy_project
$ chmod g+rw /etc/nginx/sites-available/steves_dodgy_project

### Let all members of the staff group edit the group_website config:
$ chgrp staff /etc/nginx/sites-available/group_website
$ chmod g+rw /etc/nginx/sites-available/group_website
Run Code Online (Sandbox Code Playgroud)

如果您需要更细粒度的控制(例如:只有 3 个用户可以访问,但不是所有员工),您可以使用该addgroup命令创建一个新组,并向其中添加几个用户。


让用户通过编辑文件 sudo

这个答案的其余部分变成了一项调查,调查sudo在尝试为用户提供灵活性时在配置中留下漏洞是多么容易。我不建议做以下任何事情!

如果您想授予您的用户编辑特定文件的权限,您可以尝试使用rnano

%staff ALL = /bin/rnano /etc/nginx/sites-available/host
Run Code Online (Sandbox Code Playgroud)

rnano只会让他们编辑指定的文件。这对于防止恶意用户编辑不同的 upstart 服务(例如/etc/init.d/urandom)并在其中添加一行运行service network restart.

不幸的是,我没有找到一种rvim充分限制的方法(用户仍然可以使用 来打开任何文件:e),所以我们坚持使用nano.

不幸的是,允许用户编辑多个文件要困难得多......


让用户编辑多个文件(比应该的困难得多)

1. 不安全的方法

小心通配符!如果你提供太多的灵活性(或任何灵活性),它可以被利用:

%staff ALL = /bin/rnano /etc/nginx/sites-available/*                # UNSAFE!
Run Code Online (Sandbox Code Playgroud)

在这种情况下,恶意用户将能够编辑任何其他新贵服务脚本,然后运行它:

$ sudo rnano /etc/nginx/sites-available/../../../any/file/on/the/system
Run Code Online (Sandbox Code Playgroud)

(Sudo 实际上确实阻止...扩展了命令,但不幸的是不是在参数上。)

我希望这样的事情可能会奏效,但它仍然不安全:

%staff ALL = /bin/rnano /etc/nginx/sites-available/[A-Za-z0-9_-]*   # UNSAFE!
Run Code Online (Sandbox Code Playgroud)

由于sudo目前仅提供glob模式,因此*可以匹配任何内容- 它不是正则表达式!

(编辑:我确实考虑过在您的情况下您是否可以摆脱上述情况,因为下面没有子文件夹sites-available。我们确实要求在文件夹后匹配一个字符,并且/..应该在文件名后失败。但这不是可行的解决方案,因为rnano接受多个参数。而且总的来说,这在具有子文件夹的文件夹上仍然是不安全的!)

即使我们没有子文件夹,并且我们排除了任何包含/../的行,*仍然可以利用提供glob的规则,因为它rnano接受多个参数(在 上循环它们<C-X>,并且*glob愉快地接受了空间。

$ rnano /etc/nginx/sites-available/legal_file /then/any/file/on/the/system
Run Code Online (Sandbox Code Playgroud)

2.推动信封(最终也是不安全的)

那么如果我们拒绝任何包含空格或试图到达的行/..呢?那么最终可行的解决方案可能是这样的:

# I tried hard to make this safe, but in the end I failed again.
# Please don't use this unless you are really smart or really stupid.

%staff ALL =   /bin/rnano /etc/nginx/sites-available/*,    \
             ! /bin/rnano */..*,                           \
             ! /bin/rnano /etc/nginx/sites-available/,     \
             ! /bin/rnano */.,                             \
             ! /bin/rnano * *

# CONCLUSION: It is still NOT SAFE if there are any subfolders, due to
# the bug in rnano described below.
Run Code Online (Sandbox Code Playgroud)

我们接受文件夹“下”的任何内容,但我们也拒绝任何对rnanoif/../.or 的调用,或者如果文件夹是直接目标。(从技术上讲,/.排除会使排除变得/..多余,但为了清楚起见,我将两者都留了下来。)

我发现文件夹和/.排除项是必需的,否则用户可以定位文件夹本身。现在你可能认为rnano如果指向一个文件夹会阻塞,但你错了。实际上,我的版本 (2.2.6-1ubuntu1) 以轻微警告和一个空文件启动,然后<C-X>要求我输入我想保存的任何文件名,打开一个新的攻击向量!好吧,至少它拒绝覆盖现有文件(在我做的一个测试中)。无论如何,由于无法使用 sudo 将子文件夹列入黑名单,因此我们必须得出结论,这种方法再次不安全。对不起用户!

这个发现让我怀疑nano“受限”模式的彻底性。他们说链条的强度取决于其最薄弱的环节。我开始感受到sudo黑名单黑魔法的结合,rnano可能不会比一串雏菊更安全。

3. 安全但有限的方法

Glob 非常受限制——它们不允许我们多次匹配一个字符类。如果所有文件名的长度相同(在本例中后跟一个数字),您可以提供多个文件编辑host

%staff ALL = /bin/rnano /etc/nginx/sites-available/host[0-9]       # SAFE
Run Code Online (Sandbox Code Playgroud)

但是,如果您想授予用户编辑各种文件的权限,您可能需要明确指定每个文件:

%staff ALL = /bin/rnano /etc/nginx/sites-available/hothost    \
             /bin/rnano /etc/nginx/sites-available/coldhost   \    # SAFE
             /bin/rnano /etc/nginx/sites-available/wethost    \
             /bin/rnano /etc/nginx/sites-available/steves_dodgy_project
Run Code Online (Sandbox Code Playgroud)

不要试图*在任何时候使用 a。请参阅上面的第 1. 和第 2. 节了解原因!请记住:一个小错误可能会危及整个超级用户帐户和整个系统。

4. 编写你自己的参数检查器(安全现在是你的责任)

我希望他们将来会添加正则表达式支持sudo;如果使用得当,它可以解决很多问题。但是我们可能还需要能够检查参数的属性(只允许文件、文件夹或某些标志)。

但是有一种替代方法可以在 sudo 中创建灵活性。把钱递过去:

%staff ALL = /root/bin/staffedit *
Run Code Online (Sandbox Code Playgroud)

然后编写自己的staffedit脚本或可执行文件来检查用户传递的参数是否合法,只有在合法时才执行他们的请求。

  • 这个答案花了很长时间,但最后我想我明白了 sudo 是如何工作的。过去我曾多次放弃,发现 `ALL=(ALL:ALL) ALL` 太缺乏语义,但我一直认为它会有一个不错的参数检查器......我错了。它真的非常有限。甚至手册页中提供的 passwd root 排除也可以通过一个简单的命令行参数“sudo passwd -q root”来破坏。那么 sudo 作者确实在他们的网站上列出了 [一些替代方案](sudo.ws/sudo/other.html)。我希望他们将来会添加正则表达式支持。 (5认同)

小智 5

首先,打开 sudoers 文件sudo visudo。添加user ALL=!/usr/sbin/service将,IIRC,禁止serviceuser的命令user

来源:http : //nixcraft.com/showthread.php/15132-Sudo-Exclude-Commands-And-Disable-sudo-su-Bash-Shell

  • 在许多情况下,白名单是不可维护的。真正的目标可能不是*阻止*他们做某事,而是在不以其他方式限制他们的情况下防止他们错误地做坏事。在这些情况下,黑名单很好。您将合理的用户执行任务的方式列入黑名单。但是通过 sudo 列入黑名单可能还不够——人们可以并且确实使用“sudo bash”。一种方法是包装“服务”命令,如果您不希望他们使用,请通知他们。但是你永远不会在白名单中列出所有好的行为,也不会在黑名单中列出所有的坏行为。 (3认同)
  • 是的,但仍然像其他人所说的那样,你必须非常小心。获取访问权限的方法有很多。任何可以生成 shell 等的命令。它更容易找出他们真正需要什么命令并允许它们,而不是试图排除所有“禁止”的命令。 (2认同)

she*_*har 5

我找到了解决办法。

我已经打开终端并更改为 root 用户,su -然后输入visudo进行编辑。

然后最后我写了几行

user ALL=!/etc/init.d/NetworkManager restart
user ALL=!/etc/init.d/network restart
Run Code Online (Sandbox Code Playgroud)

然后我也保存并关闭并重新启动。

现在,如果我输入 asservice network restartservice NetworkManager restartthen 它不允许我并给出类似的错误

Sorry user is not allowed to execute '/sbin/service NetowkrManager restart' as root on localhost.localdomain
Run Code Online (Sandbox Code Playgroud)

service network restart命令也类似。

  • 这适用于没有经验和恶意的用户,但很容易绕过 sudo 限制,(例如`sudo cp -p /etc/init.d/network /etc/init.d/network-not-in-sudo` 然后`sudo /etc/init.d/network-not-in-sudo restart`)。这就是为什么在 sudoers 文件中创建包含而不是排除更安全的原因,例如,说明允许与哪些服务交互。 (13认同)

rei*_*rab 5

对此的真正答案是,您无法真正阻止这种情况。您可能会通过其他答案中描述的方法防止恶意人员意外运行该命令,但是如果有人真的想运行它并且在 sudoers 列表中,他们可以运行它。例如,他们可以执行以下操作:

joe@box:~$ sudo bash root@box:~# service network restart

或者他们可以用来规避您在 sudoers 文件中的限制的另一个有趣的命令:

sudo visudo

长话短说,如果你可以 sudo 并且它不限于运行特定命令,你几乎可以做任何你想做的事情。即使您将它们限制为一组给定的命令,您也必须确保用户无法将他们想要运行的其他命令复制到与他们有权运行的命令相同的名称(例如通过覆盖他们有权运行的命令。)