Find

如何搜尋具有不可變屬性集的文件?

  • May 3, 2021

出於配置審計的原因,我希望能夠在我的 ext3 文件系統中搜尋具有不可變屬性集(通過chattr +i)的文件。我找不到find執行此操作的任何選項或類似選項。在這一點上,恐怕我必須編寫自己的腳本來解析lsattr每個目錄的輸出。是否有提供更好方法的標準實用程序?

它可以通過通過lsattr命令傳遞grep命令來部分完成。

lsattr -R | grep +i

但是,我相信當您提到搜尋可能涉及的整個ext3文件系統以及其他一些可能會報告您只想忽略的錯誤的目錄時。您可能可以將命令執行為,/proc``/dev

lsattr -R 2>/dev/null | grep -- "-i-"

您可能希望通過使用的 PCRE 工具來更明確地匹配“-i-” ,從而使其grep更加嚴格。grep

lsattr -R 2>/dev/null | grep -P "(?<=-)i(?=-)"

這將適用於以下情況:

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

但卻是不完美的。如果在不可變標誌周圍啟用了其他屬性,那麼我們將不匹配它們,這將被名稱恰好與上述模式匹配的文件所迷惑,例如:

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

我們可以像這樣收緊模式:

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

但它仍然有點太脆弱,需要根據文件系統中的文件進行額外的調整。更不用說@StephaneChazeles在評論中提到,通過包含帶有文件名的換行符來繞過上述模式到grep.

參考

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

鑑於腳本的目的是審計,正確處理任意文件名尤其重要,例如包含換行符的名稱。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 {} +

我建議使用不那麼古怪的語言,例如 Perl、Python 或 Ruby,並自己完成工作lsattrlsattr通過發出FS_IOC_GETFLAGSioctl 系統呼叫並檢索文件的inode 標誌來進行操作。這是一個 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)

引用自:https://unix.stackexchange.com/questions/132795