특정 사용자가 읽을 수 없는 파일을 찾고 싶습니다.
사용자 이름이 "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 ) 이는 두 개의 동일한 명령문입니다.
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 연산자를 통해서만 가능할 것입니다. and/or/not을 사용하여 XOR을 구성할 수 있지만 위의 두 솔루션보다 더 복잡합니다.
답변1
사용자가 지정된 경로를 통해 파일에 액세스할 수 있는지 확인하려면 고려해야 할 사항이 더 많이 있습니다.
- 파일 소유자
- 파일 그룹
- 파일의 ACL
- 사용자의 uid, gid 및 보충 gid
- 검색은 파일로 연결되는 모든 경로 구성 요소에 액세스합니다.
- 파일이 심볼릭 링크인지 여부
- 사용자 ID 0의 경우 권한이 다르게 적용됩니다.
- SELinux와 같은 더 많은 보안 기능이 있을 수 있습니다.
실제로 모든 uid와 gid를 사용자의 uid와 gid로 전환하고 확인하지 않고서는 시스템과 동일한 로직을 구현하기 어려울 것입니다.
zsh를 사용하면 루트로 다음을 수행할 수 있습니다.
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
. 그러나 두 번째 조건(그룹이 소유 user123
하고 그룹의 r
비트가 설정되지 않음)을 충족하기 때문에 나열됩니다.
두 번째 버전은 다음 이유 중 하나로 인해 작동합니다.드모건의 법칙: 명령문 그룹의 논리적 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
...