如何搜索具有不可变属性集的文件?

dep*_*uid 21 find ext3

出于配置审核的原因,我希望能够在我的 ext3 文件系统中搜索具有不可变属性集(通过chattr +i)的文件。我找不到任何find可以执行此操作的选项或类似选项。在这一点上,恐怕我必须编写自己的脚本来解析lsattr每个目录的输出。是否有提供更好方法的标准实用程序?

Ram*_*esh 10

它可以lsattr通过grep命令管道命令来部分完成。

lsattr -R | grep +i
Run Code Online (Sandbox Code Playgroud)

但是,我相信当您提到整个ext3文件系统时,搜索可能涉及/proc/dev以及其他一些可能报告一些您只想忽略的错误的目录。您可能可以将命令运行为,

lsattr -R 2>/dev/null | grep -- "-i-"
Run Code Online (Sandbox Code Playgroud)

您可能希望grep通过使用grep的 PCRE 工具来更严格地匹配“-i-”。

lsattr -R 2>/dev/null | grep -P "(?<=-)i(?=-)"
Run Code Online (Sandbox Code Playgroud)

这将适用于以下情况:

$ lsattr -R 2>/dev/null afile | grep -P "(?<=-)i(?=-)"
----i--------e-- afile
Run Code Online (Sandbox Code Playgroud)

但是是不完美的。如果在 immutable 标志周围启用了其他属性,那么我们将不会匹配它们,并且这将被名称恰好与上述模式匹配的文件所欺骗,例如:

$ lsattr -R 2>/dev/null afile* | grep -P "(?<=-)i(?=-)"
----i--------e-- afile
-------------e-- afile-i-am
Run Code Online (Sandbox Code Playgroud)

我们可以像这样收紧模式:

$ lsattr -a -R 2>/dev/null afile* | grep -P "(?<=-)i(?=-).* "
----i--------e-- afile
Run Code Online (Sandbox Code Playgroud)

但它仍然有点过于脆弱,需要根据文件系统中的文件进行额外的调整。更不用说@StephaneChazeles在评论中提到的,通过包含带有文件名的换行符来绕过上述模式,这可以很容易地进行游戏grep

参考

https://groups.google.com/forum/#!topic/alt.os.linux/LkatROg2SlM

  • 可能不利于审计,因为使用这种方法可以通过在文件名中包含换行符来伪造或隐藏不可变文件。此外,文件名中包含“-i-”的情况并不少见(我当前登录的系统上有 34 个)。您可能还需要 `-a` 选项 (2认同)
  • 为什么不简单地 grep 为`^....i`?或者至少像 `^[^ ]*i` 之类的东西,如果 `i` 可以位于第五位以外的其他位置。 (2认同)

Gil*_*il' 8

鉴于脚本的目的是审计,正确处理任意文件名尤其重要,例如包含换行符的名称。这使得无法lsattr同时在多个文件上使用,因为lsattr在这种情况下输出可能不明确。

您可以一次递归find调用lsattr一个文件。不过会很慢。

find / -xdev -exec sh -c '
  for i do
     attrs=$(lsattr -d "$i"); attrs=${attrs%% *}
     case $attrs in
       *i*) printf "%s\0" "$i";;
     esac
  done' sh {} +
Run Code Online (Sandbox Code Playgroud)

我建议使用不那么古怪的语言,例如 Perl、Python 或 Ruby,并自己完成工作lsattrlsattr通过发出FS_IOC_GETFLAGSioctl 系统调用并检索文件的inode flags 进行操作。这是一个 Python 的概念验证。

#!/usr/bin/env python2
import array, fcntl, os, sys
S_IFMT =  0o170000
S_IFDIR = 0o040000
S_IFREG = 0o100000
FS_IOC_GETFLAGS = 0x80086601
EXT3_IMMUTABLE_FL = 0x00000010
count = 0
def check(filename):
    mode = os.lstat(filename).st_mode
    if mode & S_IFMT not in [S_IFREG, S_IFDIR]:
        return
    fd = os.open(filename, os.O_RDONLY)
    a = array.array('L', [0])
    fcntl.ioctl(fd, FS_IOC_GETFLAGS, a, True)
    if a[0] & EXT3_IMMUTABLE_FL: 
        sys.stdout.write(filename + '\0')
        global count
        count += 1
    os.close(fd)
for x in sys.argv[1:]:
    for (dirpath, dirnames, filenames) in os.walk(x):
        for name in dirnames + filenames:
            check(os.path.join(dirpath, name))
if count != 0: exit(1)
Run Code Online (Sandbox Code Playgroud)


dep*_*uid 4

感谢 Ramesh、slm 和 St\xc3\xa9phane 为我指明了正确的方向(我错过-Rlsattr。不幸的是,到目前为止,没有一个答案对我来说正确。

\n\n

我想出了以下几点:

\n\n
lsattr -aR .//. | sed -rn '/i.+\\.\\/\\/\\./s/\\.\\/\\///p'\n
Run Code Online (Sandbox Code Playgroud)\n\n

这可以防止使用换行符使文件看起来是不可变的,而实际上它并不是。它不能防止设置为不可变且文件名中包含换行符的文件。但由于这样的文件必须由 root 以这种方式创建,所以我可以确信在我的用例中我的文件系统上不存在这样的文件。(在 root 用户可能受到威胁的情况下,此方法不适合入侵检测,但也不适合使用lsattr也属于同一 root 用户的同一系统实用程序。)

\n