查找用户无法阅读的文件?


12

我想查找特定用户将无法读取的文件。

假设用户名是“ user123”,并且它们在一个名为“ user123”的组中。我想找到的文件,如果它们是user123所拥有的,则打开u + r;失败,如果该文件是组user123,则应启用g + r;否则它可能会打开o + r。

由于GNU find具有“可读性”,因此我可以这样做:

sudo -u user123 find /start ! -readable -ls

但是,该过程必须由没有sudo访问权限的用户运行。因此,II尝试了此操作:(它不检查o + r,但在这一点上并不重要)

find /start \( -user user123 ! -perm -u=r  \) -o \( -group user123 ! -perm -g=r  \) -ls

但它列出了该文件:

272118    4 -rw-------   1 user123   user123       3243 Jul  3 19:50 /start/blah/blah/file.txt

该文件是/startuser123 下所有具有g=roff 的唯一文件。好像find在解释-u=ras -g=r

我决定尝试逆转逻辑,而是进行测试not ( truth )

find /etc/puppet ! \( \( -user puppet -perm -u=r  \) -o \( -group puppet -perm -g=r \) -o \( -perm -o=r \) \)  -ls

那个有效!

为什么原始文件find会失败?是find(不太可能)存在错误还是逻辑错误?

更新:我的逻辑有误。如下面所指出的,因为!(A || B || C)==(!A &&!B &&!C)这是两个等效的语句:

find /start ! \( \( -user user123 -perm -u=r \) -o \( -group user123 -perm -g=r \) -o \( ! \( -user user123 -o -group user123 \) -perm -o=r \) \) -ls
find /start ! \( -user user123 -perm -u=r \) ! \( -group user123 -perm -g=r \) ! \( ! \( -user user123 -o -group user123 \) -perm -o=r \) -ls

我的目标是不必两次测试用户/组。我真正需要的是一个更复杂的if-then-else结构,只有在有-xor运算符的情况下才可能实现。我可以用和/或不可以构建异或,但是它比上面的两个解决方案要复杂得多。


1
甚至第二种逻辑也是错误的,因为它表示puppet可以使用来访问文件--wxrwxrwx puppet puppet
斯特凡Chazelas

Answers:


7

逻辑是错误的。您认为该文件不应该被列出,因为它是该文件的所有者,user123并且已r设置了用户的位。但是,它之所以被列出是因为它与第二个条件匹配(归组所有,user123并且未r设置组的位)。

您的第二个版本之所以起作用,是因为de Morgan的一条定律:否定一组语句的逻辑“或”在逻辑上等效于“与”逻辑各个语句的“否”。换一种说法:

 ! ( A || B || C ) == ( !A && !B && !C )

所以工作find正在寻找一个文件

  • 不是(由用户拥有user123并由所述用户读取)并且
  • 不是(归群组所有并由该群组user123可读)并且
  • 不是世界可读的。

而第一个find正在寻找的文件

  • 归用户所有,该用户user123不可读或
  • 由组拥有,user123并且不能由所述组读取,或者(如果您已完成)
  • 不可读

因此,如您所见,将列出与以上3个条件中的任何一个(不一定是全部)匹配的文件。

编辑

顺便说一句(查看您的个人资料之后),我非常喜欢您的O'Reilly书:)


感谢您的分析。是的,这是摩根法律的错误适用。我试图这样做,( !A && !B && !C )但是我将其移动!到每个零件的内部,这是无效的。谢谢!
TomOnTime

PS:很高兴您是我的书的粉丝!我很好奇,你读它的语言。
TomOnTime

@TomOnTime英语,当然。如果可以的话,我会尝试以原始语言阅读任何书籍。
Joseph R.

8

检查用户是否可以通过给定路径访问文件还有很多事情要考虑:

  • 文件的所有者
  • 文件组
  • 文件中的ACL
  • 用户的uid,gid和补充gids
  • 搜索对导致该文件的任何路径组件的访问。
  • 该文件是否为符号链接
  • 权限对ID为0的用户的适用方式有所不同。
  • 可能会有更多安全功能,例如SELinux ...

由于实际上没有将所有的uid和gid切换到用户的uid和gid并进行检查,因此很难实现与系统相同的逻辑。

使用zsh,您可以(以root用户身份)执行以下操作:

readable() (
  USERNAME=$u
  [ -r "$REPLY" ]
)
u=some-user
print -rl -- **/*(DoN^+readable)

或搭配perl

find . -print0 | sudo -u some-user perl -Mfiletest=access -l -0ne '
  print unless -r'

在这两种情况下,都将目录树作为降级,root但是以相应的用户身份测试文件访问权限。

在这种情况下,将无法运行,find -readable因为some-user它将无法越过用户没有访问权限或读取权限(但可能具有访问权限)的目录。

即使仅考虑文件本身的许可和所有权(而不考虑ACL或路径组件...),也至少需要(此处为GNU语法):

u=some-user; g=$(id -G "$u" | sed 's/ / -o -group /g'); IFS=" "
find . ! \( -user "$u" -perm -u=r -o \
          ! -user "$u" \( -group $g \) -perm -g=r -o \
          ! -user "$u" ! \( -group $g \) -perm -o=r \)

这样的想法是,如果文件归用户所有,则其他所有权限都不相关。如果不是,则如果该文件由用户的任何组归组所有,则“其他”权限无关紧要。


1
关于ACL和其他因素的要点。唯一100%正确的评估是access()因为它使用与相同的内核代码open()sudo -u user123 find /start -readable如果sudo可以的话,这是最好的解决方案。
TomOnTime

1
@TomOnTime。好吧,不,如果您使用sudo -u user123 find -readable,它将不会报告您无法输入的目录或您无法读取的目录中的文件(因此将出现误报和误报)。这就是为什么我建议使用zsh的降目录树的根,做access()[ -r ... ])为实际用户(设置$USERNAMEzsh改变所有的UID和GID一样sudo会)。
斯特凡Chazelas
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.