파일 · 권한 · 사용자 관리 44 / 50 · Part 5. 권한 상승과 Linux 보안
실습 환경: Rocky Linux 9.8 · Ubuntu 24.04.5 (Docker 격리 컨테이너, 테스트 계정analyst)
기초편 연계: 「리눅스 시스템 기초」 16. chmod와 권한 관리
지금까지 다룬 권한 체계(9비트)에는 근본적인 한계가 있다. 주체가 소유자·그룹·기타 셋뿐 이다. "이 파일을 특정 사용자 한 명에게만 읽기 허용"은 9비트로 표현할 수 없다. 그 사용자를 위한 그룹을 따로 만들어야 한다.
이 한계를 해결하는 것이 ACL(Access Control List) 이다. setfacl/getfacl로 개별 사용자·그룹에 세밀한 권한 을 부여할 수 있다. 이번 글에서는 ACL의 기본 사용과, 초보자가 가장 헷갈리는 mask와 유효 권한 을 실습으로 확인한다. 12편에서 본 ls -l의 + 표시가 바로 ACL의 존재 신호다.
9비트 권한은 "소유자 / 그룹 / 기타"만 구분한다. 다음은 9비트로 불가능하다.
ACL은 이를 named user/group 항목으로 해결한다.
| 명령 | 동작 |
|---|---|
setfacl -m u:user:rwx f | 사용자에게 권한 부여 |
setfacl -m g:group:rx f | 그룹에게 권한 부여 |
setfacl -m m::r f | mask 설정 |
setfacl -x u:user f | 특정 항목 제거 |
setfacl -b f | ACL 전체 제거 |
setfacl -d -m ... dir | 기본(default) ACL — 하위 상속 |
getfacl f | ACL 조회 |
ACL에는 mask 라는 특별한 항목이 있다. mask는 named user/group과 그룹 소유자의 유효 권한 상한 이다. user:contractor:rw-로 부여해도 mask가 r--면 실제 권한은 r--가 된다(#effective:r--). 그리고 ls -l의 그룹 권한 자리는 실제로는 mask를 표시 한다. 이 점을 모르면 권한을 잘못 읽는다.

파일에 ACL을 설정하면 확장 속성(xattr)에 접근 규칙 목록이 저장된다. 커널은 권한 검사 시 다음 순서로 확인한다.
mask가 상한으로 작동하는 것은 안전장치다. chmod로 그룹 권한을 조정하면 mask가 함께 바뀌어, ACL로 부여한 권한이 의도치 않게 넓어지는 것을 막는다. 그래서 ACL이 걸린 파일에 chmod g-w를 하면 named user의 쓰기 권한도 함께 제한될 수 있다.
ls -l에 +가 붙는 것은 "9비트 외에 ACL 규칙이 있다"는 신호다(12편). 보안 점검에서 + 파일은 반드시 getfacl로 실제 접근 범위를 확인해야 한다.
report.txt는analyst:analyst소유의640파일이다.contractor는 analyst 그룹이 아니라 원래 접근할 수 없다.
cd /data/lab44
# 1) 기존 권한 (contractor 접근 불가)
ls -l report.txt
# 2) ACL 로 contractor 에게만 읽기 부여
setfacl -m u:contractor:r report.txt
getfacl report.txt
# 3) ls 에 + 표시
ls -l report.txt
# 4) mask 와 유효 권한
setfacl -m u:contractor:rw report.txt # rw 부여
setfacl -m m::r report.txt # 하지만 mask 를 r 로
getfacl report.txt | grep -E 'contractor|mask' # effective r--
# 5) ACL 제거
setfacl -x u:contractor report.txt && setfacl -b report.txt && ls -l report.txt

텍스트 원본(실제 출력):
[analyst@rocky9-lab ~]$ cd /data/lab44
[analyst@rocky9-lab lab44]$ echo "=== 기존 권한: 640 (그룹 analyst 만 읽기) ==="
=== 기존 권한: 640 (그룹 analyst 만 읽기) ===
[analyst@rocky9-lab lab44]$ ls -l report.txt
-rw-r----- 1 analyst analyst 20 Sep 24 15:00 report.txt
[analyst@rocky9-lab lab44]$ echo "=== contractor 는 접근 불가 (그룹 아님) ==="
=== contractor 는 접근 불가 (그룹 아님) ===
[analyst@rocky9-lab lab44]$ echo "=== ACL 로 contractor 에게만 읽기 부여 ==="
=== ACL 로 contractor 에게만 읽기 부여 ===
[analyst@rocky9-lab lab44]$ setfacl -m u:contractor:r report.txt
[analyst@rocky9-lab lab44]$ getfacl report.txt
# file: report.txt
# owner: analyst
# group: analyst
user::rw-
user:contractor:r--
group::r--
mask::r--
other::---
[analyst@rocky9-lab lab44]$ echo "=== ls 에 + 표시 등장 ==="
=== ls 에 + 표시 등장 ===
[analyst@rocky9-lab lab44]$ ls -l report.txt
-rw-r-----+ 1 analyst analyst 20 Sep 24 15:00 report.txt
[analyst@rocky9-lab lab44]$ echo "=== mask 와 유효 권한 ==="
=== mask 와 유효 권한 ===
[analyst@rocky9-lab lab44]$ setfacl -m u:contractor:rw report.txt
[analyst@rocky9-lab lab44]$ setfacl -m m::r report.txt
[analyst@rocky9-lab lab44]$ getfacl report.txt | grep -E 'contractor|mask'
user:contractor:rw- #effective:r--
mask::r--
[analyst@rocky9-lab lab44]$ echo "=== ACL 제거 ==="
=== ACL 제거 ===
[analyst@rocky9-lab lab44]$ setfacl -x u:contractor report.txt && setfacl -b report.txt && ls -l report.txt
-rw-r----- 1 analyst analyst 20 Sep 24 15:00 report.txt
| 출력 | 해석 |
|---|---|
-rw-r----- report.txt | 초기 640. contractor는 other(---)라 접근 불가 |
getfacl → user:contractor:r-- | contractor에게만 읽기 부여 |
mask::r-- | 유효 권한 상한 |
-rw-r-----+ report.txt | + 표시 등장 = ACL 존재 |
user:contractor:rw- #effective:r-- | rw로 부여했지만 mask가 r--라 실효는 r-- |
mask::r-- | mask가 유효 권한을 제한 |
setfacl -b 후 -rw-r----- | ACL 제거, + 사라짐 |
user:contractor:rw- #effective:r--가 핵심이다. 부여한 권한(rw)과 실제 적용되는 권한(r)이 다르다. mask를 모르면 "쓰기를 줬는데 왜 안 되지?"라고 착각한다.
| 주제 | 내용 |
|---|---|
| 9비트 은폐 | ACL로 열린 접근은 ls -l 9비트에 안 보인다. +와 getfacl로 확인 |
| 최소 권한 | 그룹을 남발하는 대신 ACL로 개별 부여 → 관리 명확 |
| mask 주의 | chmod가 mask를 바꿔 ACL 권한이 예상과 달라질 수 있음 |
| 백업·복사 | ACL 보존은 cp -a, rsync -A, tar --acls(09편) |
| 기본 ACL | 디렉터리 default ACL은 하위에 상속 → 광범위 부여 주의 |
점검 포인트: 공격자가 민감 파일에 ACL로 자기 계정 접근을 추가하는 것은 은밀한 백도어다. ls -l만으로는 안 보이므로 + 표시 파일을 getfacl로 전수 확인 한다.
[점검] ACL 이 설정된 파일 전수 확인
find /etc /home /var/www -type f 2>/dev/null | while read f; do
getfacl -s "$f" 2>/dev/null | grep -q . && echo "ACL: $f"
done
# 또는 ls -l 의 + 표시 파일 → getfacl
↓
[이상] 민감 파일에 예상 밖 named user/group ACL
↓
[Evidence] getfacl 결과, 파일 ctime(ACL 변경도 ctime 갱신), setfacl 실행 로그
↓
[Detection] setfacl 실행·xattr 변경을 auditd 로 감시
↓
[Response] 무단 ACL 제거(setfacl -x/-b), 경위 조사
| 관점 | 내용 |
|---|---|
| 은폐 탐지 | + 표시 없이 9비트만 보면 ACL 백도어를 놓친다 |
| Detection | setfacl·setxattr 시스템 콜을 auditd로 감시 |
| Baseline | 민감 경로의 정상 ACL을 기준값으로 관리 |
| 실수 | 결과 | 예방 |
|---|---|---|
| mask 무시 | 부여한 권한이 안 먹힘 | #effective 확인 |
ls -l만으로 권한 판단 | ACL 접근 누락 | + → getfacl |
chmod로 ACL 권한 변경 시도 | mask만 바뀜 | setfacl 사용 |
| 복사 시 ACL 손실 | 권한 누락 | cp -a, rsync -A |
| default ACL 광범위 부여 | 하위 전체 노출 | 필요 범위만 |
[ ] setfacl 로 특정 사용자에게만 권한을 부여했다
[ ] getfacl 로 ACL 을 조회했다
[ ] ls -l 의 + 표시를 확인했다
[ ] mask 로 유효 권한이 제한되는 것을 확인했다
[ ] #effective 표시를 해석할 수 있다
[ ] + 표시 파일을 getfacl 로 점검하는 방법을 안다
setfacl -m u:user:권한으로 부여, getfacl로 조회, -b로 제거한다.#effective)이 다를 수 있다.ls -l의 그룹 자리는 mask를 보여 주며, +가 ACL 존재를 뜻한다.+ 파일을 getfacl로 확인한다.cp -a·rsync -A, 변경 감시는 auditd로 한다.다음 글 「45. 파일 권한과 최소 권한 원칙」 에서는 지금까지 배운 권한·소유권·특수 권한·ACL을 최소 권한 원칙(Least Privilege) 이라는 하나의 설계 철학으로 묶는다. systemd 서비스 격리와 capabilities로 "root 없이 필요한 권한만" 주는 방법을 다룬다.