用sudo安全地使用find

在Linux服务器上,我需要从一组用户中删除root权限。 但是这些用户有合法的理由能够使用“查找”实用程序根据文件名,修改date和其他元数据来search文件。

在服务器上,文件名不敏感,但文件内容可能是。

我想使用sudo来允许用户search服务器上任何地方的文件。 “查找”实用程序是很好的,但它允许各种副作用,如使用“-exec”来产生任意命令。

我可以find与我的限制工作吗?

那么find什么?

定位读取由updatedb(8)准备的一个或多个数据库,并将至less匹配其中一个PATTERN的文件名写入标准输出,每行一个。 如果未指定–regex,则PATTERN可以包含通配符。 如果任何PATTERN不包含通配符,则查找模式为PATTERN的行为。

默认情况下,locate不检查在数据库中find的文件是否仍然存在。 定位不能报告在相关数据库的最近更新之后创build的文件。

或者甚至可能slocate :

Secure Locate提供了一种安全的方式来索引和快速search系统上的文件。 它使用像GNU定位的增量编码来压缩其数据库以加快search速度,但它也将存储文件权限和所有权,以便用户不会看到他们无权访问的文件。

本手册页logging了slocate的GNU版本。 slocate使系统用户可以search整个文件系统而不显示未经授权的文件。

根据man 7 capabilities

  CAP_DAC_READ_SEARCH * Bypass file read permission checks and directory read and execute permission checks; * Invoke open_by_handle_at(2). 

这对我有效。 (以'#'开头的行是root,'$'是非root),在这种情况下,非root用户在wheel组中。

 # cp /usr/bin/find /usr/bin/sudofind # chmod 710 /usr/bin/sudofind # chown root:wheel /usr/bin/sudofind # setcap cap_dac_read_search+ep /usr/bin/sudofind # exit $ find /root find: '/root': Permission denied $ sudofind /root /root /root /root/Testbed ... ... $ sudofind /root -exec cat {} \; cat: /root: Permission denied cat: /root/Testbed: Permission denied $ sudofind /root -printf "%u %g %m %c %p\n" root root 644 Mon Apr 20 09:20:48.0457518493 2015 /root root root 755 Fri Dec 4 02:34:03.0016294644 2015 /root/Testbed ... ... $ # Capability inheritance test.. $ sudofind /root -exec /bin/sleep 10 \; & [1] 17017 $ getpcaps $(pgrep find) Capabilities for `17017': = cap_dac_read_search+ep $ getpcaps $(pgrep sleep) Capabilities for `17019': = 

鉴于能力授予什么,它恰好符合你想要的。 我没有详尽地检查find是否有一个允许你读取文件内的字节的特性,但是像LD_PRELOAD和library shim攻击这样的明显的东西不应该工作,这是由于Linux中setuid检查的性质造成的,也不会被subprocessinheritance(不像原始setuid),所以这是另一个好处。

请记住,您要做的事情会引起对于临时文件创build或访问的可能的隐私问题,并且该程序可以用作安装竞争条件/特权升级尝试的基础(针对创build众所周知的文件名的程序但是不要做正确的安全检查)。

另外,一些写得不好的应用程序可能依靠文件元数据或树结构来传达意义或隐藏数据。 这可能会导致发布受限制的信息,或泄露不知道的特权文档(通过我所知道的安全隐患,但不幸的是,闭源代码厂商特别喜欢这样做)。

因此,小心谨慎,即使明显的事情不起作用,仍然存在与此相关的风险。

噢,我有兴趣看看是否有人有概念certificate攻击,它使用这种机制作为评论中权限升级的基础!

我会给用户适当的权限。

默认情况下,如果umask是022 ,则创build目录以便每个人都可以列出和统计其中的文件。 如果没有,您可以手动更改目录权限是按位还是旧权限, 0555

 chmod +0555 foo 

如果这些用户对该目录的所有父母(例如,另一个用户的主目录)没有执行权限,则可能意味着您应该将第一个目录放在其他位置。

如果只想让某些用户读取并执行该目录,则可以将其模式更改为0750 ,将这些用户放在一个组中,然后将该目录的组所有者更改为该组:

 groupadd can_read_foo chmod 0750 foo chgrp can_read_foo foo gpasswd -a alice can_read_foo gpasswd -a bob can_read_foo