特定のユーザーが読めないファイルを探したいです。
ユーザー名が「user123」で「user123」というグループに属しているとします。 user123が所有し、u + rが開いたファイルを見つけたいです。ファイルがグループuser123に属している場合は、g + rを開く必要があり、そうでない場合はo + rを開くことができます。
GNU findには「読み取り可能」機能があるため、次のようにできます。
sudo -u user123 find /start ! -readable -ls
ただし、このプロセスはsudoアクセス権を持っていないユーザーが実行する必要があります。だから私はこれを試しました:(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
/start
このファイルは、user123が所有して閉じた唯一のファイルですg=r
。 findが-u=r
と解釈されるのと同じです-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 ) これは 2 つの同じ文です。
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
私の目標は、ユーザー/グループを2回テストする必要がないことです。私にとって本当に必要なのは、より複雑なif-then-else構造ですが、これはおそらく-xor演算子を介してのみ可能です。 and / or / notを使用してXORを構成できますが、上記の2つのソリューションよりも複雑です。
答え1
ユーザーが指定されたパスを介してファイルにアクセスできることを確認するには、考慮すべき事項がたくさんあります。
- ファイル所有者
- ファイルグループ
- ファイルのACL
- ユーザーのuid、gid、および補足gid
- 検索は、ファイルにリンクされているすべてのパスコンポーネントにアクセスします。
- ファイルがシンボリックリンクかどうか
- ユーザー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 \)
アイデアは、ファイルがユーザー所有の場合、他のすべての権限は重要ではないということです。そうでない場合、ユーザーのグループがファイルを所有している場合、「その他」の権限は関係ありません。
答え2
ロジックが間違っています。ファイルがユーザー所有でありuser123
、ユーザービットが設定されているため、ファイルをリストしてはいけないと思いますr
。ただし、2番目の条件(グループが所有し、user123
グループのr
ビットが設定されていない)を満たすためにリストされます。
2番目のバージョンは、次のいずれかの理由で機能します。ドモーガンの法則: ステートメント・グループの論理 OR 演算の否定は、個々のステートメントの AND 演算の否定と論理的に同じです。言い換えれば:
! ( A || B || C ) == ( !A && !B && !C )
したがって、作業はfind
ファイルを見つけることです。
user123
(ユーザーが所有して読めない)user123
(グループが所有して読めない)- 世界中で読むことができません。
最初の人がfind
ファイルを探している間
- ユーザーが所有しており、
user123
そのユーザーが読めない - グループが所有しているため、
user123
グループが読み取れません。または(これを行った場合) - 世界中で読むことができない
このように、上記の3つの基準のいずれか(すべてではない)と一致するファイルが一覧表示されます。
編集する
とにかく(あなたのプロフィールを見た後)、私はあなたのO'Reilly本の熱心なファンです:)
答え3
テスト環境:
$ sudo tree -fp /tmp/del
/tmp/del
├── [drwxr-xr-x] /tmp/del/1
│ └── [-rw-r--r--] /tmp/del/1/f1
├── [d---------] /tmp/del/2
│ └── [-rw-------] /tmp/del/2/f1 <-- this filepath is not accessible for ! root
└── [drwxr-xr-x] /tmp/del/3
└── [-rw-r--r--] /tmp/del/3/f1
フル出力:
$ sudo find /tmp/del/ -type f -exec sudo -u user123 ls {} \;
/tmp/del/3/f1
/tmp/del/1/f1
ls: cannot access '/tmp/del/2/f1': Permission denied <-- required filepath
「汚い」希望の出力:
# Just redirect stdout
>/dev/null sudo find /tmp/del/ -type f -exec sudo -u user123 ls {} \;
ls: cannot access '/tmp/del/2/f1': Permission denied
再利用可能なコード
ただ隠してstdout
見せてくださいstderr
:
function xfind() { 2>&1 >/dev/null sudo find "${2}" -type f -exec sudo -u "${1}" ls {} \; | grep -o "cannot access .*$"; }
「本番」の使い方の例:ルートホームページに表示されないもの:
$ xfind $USER /root
cannot access '/root/.cache/dconf/user': Permission denied
cannot access '/root/.cache/gstreamer-1.0/registry.x86_64.bin': Permission denied
...