파일 · 권한 · 사용자 관리 28 / 50 · Part 3. Linux 파일 권한
실습 환경: Rocky Linux 9.8 · Ubuntu 24.04.5 (Docker 격리 컨테이너, 테스트 계정 analyst)
기초편 연계: 「리눅스 시스템 기초」 16. chmod와 권한 관리

1. 들어가며

일반 사용자가 passwd로 자기 비밀번호를 바꾸면, 그 정보는 /etc/shadow에 저장된다. 그런데 /etc/shadow는 root만 쓸 수 있다(보통 000 또는 640 root:shadow). 일반 사용자가 어떻게 root 전용 파일을 수정할 수 있을까?

답은 SUID(Set User ID) 다. passwd 프로그램에는 SUID가 설정되어 있어, 일반 사용자가 실행해도 파일 소유자(root)의 권한으로 동작한다. 이번 글에서는 SUID의 동작 원리를 실습으로 확인하고, 그것이 왜 권한 상승 공격에서 가장 먼저 점검하는 항목인지 정리한다.


2. 핵심 개념

2-1. 실제 UID와 유효 UID

용어의미
실제 UID (real uid)프로세스를 실행한 사용자
유효 UID (euid)권한 검사에 실제로 쓰이는 UID

보통 둘은 같다. SUID 프로그램을 실행하면 euid가 파일 소유자로 바뀐다. root 소유 SUID 파일이면 euid = 0(root)가 되어, 그 프로세스는 root 권한으로 동작한다.

2-2. SUID 표기

표시의미
-rwsr-xr-xSUID + 소유자 실행 권한 (소문자 s)
-rwSr-xr-xSUID인데 소유자 실행 권한 없음 (대문자 S, 무의미)
chmod 4755앞자리 4 = SUID
chmod u+s기호 방식

권한이 네 자리가 되는 것을 주목하자. 앞자리는 특수 권한(SUID=4, SGID=2, Sticky=1)이다.

2-3. 스크립트 SUID는 무시된다

셸 스크립트에 SUID를 설정해도 효과가 없다. Linux 커널은 인터프리터 스크립트의 SUID를 보안상 무시한다. 스크립트 SUID를 허용하면 경쟁 상태·인자 조작으로 쉽게 악용되기 때문이다. 그래서 SUID는 컴파일된 바이너리 에만 유효하다.


3. 동작 원리

SUID — 소유자 권한으로 실행되는 프로그램

커널이 SUID 파일을 실행(execve)할 때, 새 프로세스의 euid를 파일 소유자의 UID 로 설정한다. 그래서 root 소유 SUID 프로그램은 실행자와 무관하게 root 권한으로 시작한다.

passwd가 이 구조를 쓴다. passwd는 root 소유 SUID 바이너리이고, 내부적으로 자신이 root 권한임을 이용해 /etc/shadow를 수정하되, 호출한 사용자 본인의 항목만 바꾸도록 제한한다. 즉 SUID는 "권한을 빌려주되, 프로그램이 그 권한을 안전하게 쓰도록 설계"하는 방식이다.

문제는 이 "안전하게"가 깨질 때다. SUID 바이너리에 취약점이 있거나, 파일을 읽고 셸을 여는 기능이 있으면, 그 기능이 root 권한으로 실행되어 권한 상승이 된다.


4. 명령어 실습

실습용으로 myid(SUID된 id), scat(SUID된 cat), script.sh(SUID 셸 스크립트)를 root가 만들어 뒀다. secret.txt는 root 소유 600 파일이다. 격리된 테스트 환경에서만 진행한다.

cd /srv/lab28

# 1) 정상 SUID 파일 (참고)
ls -l /usr/bin/passwd              # -rwsr-xr-x root root

# 2) 실습 SUID 파일들
ls -l myid script.sh scat
id                                 # 실제 uid = 1000

# 3) SUID 바이너리 실행 → euid 변화
./myid                             # euid=0(root)

# 4) root 전용 파일 접근
cat secret.txt                     # 직접: Permission denied
./scat secret.txt                  # SUID cat: 읽힘 (euid=root)

# 5) SUID 스크립트는 무시된다
bash script.sh                     # euid 안 바뀜

5. 실행 결과

실제 실행 결과 — Rocky Linux 9.8 · analyst@rocky9-lab — SUID 와 euid

텍스트 원본(실제 출력):

[analyst@rocky9-lab ~]$ cd /srv/lab28
[analyst@rocky9-lab lab28]$ ls -l /usr/bin/passwd
-rwsr-xr-x 1 root root 32656 May 15  2022 /usr/bin/passwd
[analyst@rocky9-lab lab28]$ ls -l myid script.sh scat
-rwsr-xr-x 1 root root 40472 Sep 24 10:57 myid
-rwsr-xr-x 1 root root 36312 Sep 24 10:57 scat
-rwsr-xr-x 1 root root    15 Sep 24 10:57 script.sh
[analyst@rocky9-lab lab28]$ id
uid=1000(analyst) gid=1000(analyst) groups=1000(analyst)
[analyst@rocky9-lab lab28]$ ./myid
uid=1000(analyst) gid=1000(analyst) euid=0(root) groups=1000(analyst)
[analyst@rocky9-lab lab28]$ cat secret.txt 2>&1 || echo "→ 직접 cat: 권한 없음"
cat: secret.txt: Permission denied
→ 직접 cat: 권한 없음
[analyst@rocky9-lab lab28]$ ./scat secret.txt 2>&1 || echo "→ SUID cat 이지만..."
root secret
[analyst@rocky9-lab lab28]$ bash script.sh
uid=1000(analyst) gid=1000(analyst) groups=1000(analyst)

6. 결과 해석

출력해석
/usr/bin/passwd → -rwsr-xr-x root root정상 SUID 바이너리
id → uid=1000(analyst)실제 사용자는 analyst
./myid → uid=1000 ... euid=0(root)SUID로 euid가 root 로 바뀜
cat secret.txt → Permission deniedanalyst 권한으로는 root 600 파일 못 읽음
./scat secret.txt → root secretSUID된 cat이 root 권한으로 읽어 냄
bash script.sh → uid=1000 ... groups=1000euid 안 바뀜. 스크립트 SUID 무시

./scat이 root 전용 파일을 읽어 낸 것이 SUID의 위력이자 위험이다. 만약 시스템에 이런 SUID된 cat이 방치되면, 누구나 /etc/shadow를 읽을 수 있는 백도어가 된다.


7. 보안 관점

주제내용
정상 SUIDpasswd, sudo, su, mount, ping(일부) 등 root 권한이 꼭 필요한 소수의 프로그램
위험 신호표준 목록에 없는 SUID, 특히 cat/cp/bash/find/vim 같은 범용 도구의 SUID
GTFOBins많은 표준 도구는 SUID가 붙으면 셸 탈출·파일 읽기로 권한 상승이 가능하다. find, vim, less, awk 등
지속성root를 얻은 공격자가 cp /bin/bash /tmp/.b; chmod u+s /tmp/.b로 SUID 셸을 숨겨 둔다(09편)

핵심 방어: SUID 파일 목록을 기준값으로 관리 하고, 새로 생긴 SUID를 탐지한다(47편). SUID를 최소화하고, mount -o nosuid로 사용자 쓰기 가능 파일 시스템에서 SUID를 무력화한다.

# 사용자 데이터 파티션에서 SUID 무력화
mount -o remount,nosuid /home

8. 보안관제 관점

[Baseline]   초기 SUID 목록 저장
   find / -xdev -perm -4000 -type f 2>/dev/null | sort > /var/lib/baseline/suid.txt
     ↓
[정기 점검]  현재 목록과 비교
   diff <(find / -xdev -perm -4000 -type f 2>/dev/null | sort) /var/lib/baseline/suid.txt
     ↓
[Detection]  auditd: chmod 로 SUID 설정 시도 (권한 상승 준비)
   -a always,exit -F arch=b64 -S chmod,fchmod,fchmodat -F auid>=1000 -k suid_change
     ↓
[Evidence]   신규 SUID: stat(ctime·소유자), sha256sum, 패키지 소속(rpm -qf/dpkg -S)
     ↓
[Response]   비인가 SUID 제거(chmod u-s), root 획득 경로 역추적
관점내용
IOC패키지에 속하지 않는 SUID 바이너리, 범용 도구의 SUID
탐지SUID 설정(chmod u+s)은 auditd로 실시간 탐지 가능
Baseline배포판·버전마다 표준 SUID 목록이 다르므로 시스템별로 관리

9. 실무에서 자주 발생하는 실수

실수결과예방
SUID를 남발권한 상승 표면 확대꼭 필요한 프로그램만
범용 도구에 SUID즉시 권한 상승 경로절대 금지
스크립트에 SUID로 권한 위임 시도무시됨 (또는 우회 위험)래퍼 바이너리·sudo 규칙 사용
SUID 목록 미관리백도어 탐지 실패기준값 + 정기 비교
사용자 파티션에 SUID 허용악용 가능nosuid 마운트

10. 실습 체크리스트

[ ] SUID 파일 실행 시 euid 가 소유자로 바뀌는 것을 확인했다
[ ] SUID cat 이 root 전용 파일을 읽는 것을 재현했다
[ ] 실제/유효 UID 의 차이를 설명할 수 있다
[ ] 셸 스크립트의 SUID 가 무시됨을 확인했다
[ ] find -perm -4000 으로 SUID 파일을 찾을 수 있다
[ ] SUID 기준값 관리의 필요성을 이해했다

11. 핵심 정리

  • SUID 파일은 실행 시 euid가 파일 소유자로 바뀌어, 소유자 권한으로 동작한다.
  • passwd가 root 전용 /etc/shadow를 수정할 수 있는 것이 SUID 덕분이다.
  • 표기는 -rws...(소문자 s), 설정은 chmod 4755 또는 u+s.
  • 셸 스크립트의 SUID는 커널이 무시 한다. SUID는 바이너리에만 유효하다.
  • 범용 도구의 SUID·비표준 SUID는 권한 상승 경로다(GTFOBins).
  • SUID 목록을 기준값으로 관리하고, nosuid 마운트로 위험을 줄인다.

12. 다음 편 예고

다음 글 「29. SGID 권한」 에서는 SGID의 두 가지 동작 — 파일에서는 그룹 권한 실행, 디렉터리에서는 새 파일의 그룹 상속 — 을 구분하고, 그룹 협업 디렉터리의 표준 설정을 실습한다.


참고 자료


시리즈 이동

profile
코드에 숨겨진 위협을 읽고 AI로 보안의 미래를 설계합니다. 프론트엔드 개발 경험을 자산 삼아 더 견고하고 지능적인 보안 운영 시스템을 구축해 나가는 과정을 기록합니다

0개의 댓글