리눅스 시스템 기초 · 입문편 — 본문의 "N편"은 입문 과정 번호다. 번호별 글과 전체 250편 구성은 통합 로드맵에서 확인할 수 있다.

리눅스 시스템 기초 19 / 50 · Part 2. 파일·명령어·권한
실습 환경: Rocky Linux 9 (10.0.0.200) · 비교: Ubuntu 22.04
이전 글: 18. Linux 사용자와 그룹

🔗 심화 시리즈 — 「파일 · 권한 · 사용자 관리」
이 주제를 더 깊게 다룬 실무형 보안 시리즈: 41. su와 sudo의 차이 · 42. sudoers와 sudo 권한 관리 · 43. sudo 잘못된 설정과 권한 상승

1. 들어가며

18편에서 관리자 권한이 wheel(RHEL)·sudo(Ubuntu) 그룹으로 주어진다고 했다. 이번 글은 일반 계정이 실제로 root 권한을 얻는 두 가지 방법, su와 sudo 를 비교한다.

관제 관점에서 이 둘의 차이는 추적성 이다.

  • sudo는 누가, 언제, 어떤 명령을 root로 실행했는지 명령 단위로 로그에 남긴다.
  • su는 root 쉘을 연 시점 만 남고, 그 안에서 실행한 명령은 기본 로그에 남지 않는다.

권한 상승 흔적을 추적하려면 이 로그 형식을 정확히 읽을 줄 알아야 한다.


2. 핵심 개념

2-1. su와 sudo

구분su / su -sudo
요구 비밀번호대상 계정(root) 의 비밀번호본인 비밀번호
권한 범위대상 계정의 쉘 전체sudoers에서 허용한 명령만
환경su -: 대상 계정의 로그인 환경 / su: 현재 환경 일부 유지env_reset으로 초기화 (9편)
로그세션 시작·종료명령마다 기록
root 비밀번호 공유필요불필요

현재 대부분의 배포판은 sudo 사용을 권장 하고, Ubuntu는 기본적으로 root 비밀번호가 설정되어 있지 않다(root 직접 로그인 불가).

2-2. sudoers 문법

사용자  호스트=(실행계정:실행그룹)  [옵션:] 명령
roror   ALL=(ALL)                   ALL
%wheel  ALL=(ALL)                   ALL
backup  ALL=(root)                  NOPASSWD: /usr/bin/rsync
webops  ALL=(root)                  /usr/bin/systemctl restart httpd
요소의미
%wheel% = 그룹
ALL=모든 호스트에서
(ALL)어떤 계정으로든 실행 가능
NOPASSWD:비밀번호 없이 실행
명령전체 경로로 지정. ALL이면 무엇이든

sudoers는 반드시 visudo로 수정 한다. 문법 오류가 있으면 저장을 막아 주기 때문에, 잘못 저장해서 sudo 자체가 망가지는 사고를 막는다. 개별 규칙은 /etc/sudoers.d/에 파일로 분리하는 것이 관리하기 좋다.


3. 동작 원리

sudo · su 동작 흐름과 남는 로그

sudo는 root 소유 SUID 프로그램이다(16편). 그래서 일반 사용자가 실행해도 root 권한으로 동작하며, 다음 순서로 처리한다.

  1. /etc/sudoers와 /etc/sudoers.d/*에서 실행자·명령에 맞는 규칙을 찾는다.
  2. 규칙이 있으면 PAM으로 본인 비밀번호 를 확인한다. 성공하면 일정 시간(기본 5분) 재입력을 생략한다.
  3. 환경변수를 초기화하고 대상 계정(root)으로 명령을 실행한다.
  4. 결과를 /var/log/secure(Ubuntu auth.log)와 journal에 남긴다.

su는 PAM으로 대상 계정의 비밀번호 를 확인한 뒤 그 계정의 쉘을 실행한다. 이후 쉘 안의 명령은 su가 관여하지 않으므로 기록되지 않는다. su 이후 활동을 추적하려면 auditd의 execve 규칙(5편)이 필요하다. 이때 auid는 원래 로그인 계정(roror)으로 유지 되므로, root 쉘에서 실행된 명령도 원래 사용자에게 연결할 수 있다.


4. 실습

# 1) 내 sudo 권한 확인
sudo -l

# 2) sudoers 구조 확인
sudo grep -vE '^#|^$' /etc/sudoers
sudo ls -l /etc/sudoers.d/
getent group wheel

# 3) 제한된 sudo 규칙 추가 (visudo로 별도 파일 편집)
sudo useradd -m webops && sudo passwd webops
sudo visudo -f /etc/sudoers.d/webops
#   webops ALL=(root) /usr/bin/systemctl restart httpd
sudo visudo -c                       # 문법 검사

sudo -u webops sudo -l               # webops가 쓸 수 있는 명령 확인

# 4) 로그 생성과 확인
sudo cat /etc/shadow > /dev/null     # 성공 로그
su -                                 # root 비밀번호 입력 후 exit
sudo grep -E 'sudo|su\[' /var/log/secure | tail -10
sudo journalctl _COMM=sudo --since today --no-pager | tail

# 5) 정리
sudo rm /etc/sudoers.d/webops && sudo userdel -r webops

5. 결과 분석

아래 출력은 형식 설명용 예시다.

① sudo 성공 로그

Sep 23 12:01:10 rocky sudo[5402]:   roror : TTY=pts/0 ; PWD=/home/roror ; USER=root ; COMMAND=/bin/cat /etc/shadow
필드값의미
실행자roror누가
TTYpts/0원격 터미널(SSH)
PWD/home/roror어디서
USERroot어떤 권한으로
COMMAND/bin/cat /etc/shadow무엇을

② sudo 실패 로그

sudo[5410]:      lab : user NOT in sudoers ; TTY=pts/1 ; PWD=/home/lab ; USER=root ; COMMAND=/usr/bin/id
sudo[5415]:    roror : 3 incorrect password attempts ; TTY=pts/0 ; PWD=/home/roror ; USER=root ; COMMAND=/bin/bash
로그판단
user NOT in sudoers권한 없는 계정의 sudo 시도 — 탈취된 일반 계정의 권한 상승 시도 일 수 있음
incorrect password attempts비밀번호를 모르는 사람이 세션을 사용 중일 가능성
COMMAND=/bin/bash 등 쉘 실행명령 단위 추적을 피하려는 시도

③ su 로그

su[5500]: pam_unix(su-l:session): session opened for user root(uid=0) by roror(uid=1000)
su[5530]: FAILED SU (to root) roror on pts/0

su-l은 su -(로그인 쉘)로 전환했다는 뜻이다. 세션 시작 이후의 명령은 이 로그에 없다.


6. 보안 관점

위험 설정 / 행위문제대응
ALL=(ALL) NOPASSWD: ALL계정만 탈취하면 비밀번호 없이 rootNOPASSWD 최소화, 명령 한정
쉘 탈출 가능한 명령 허용vi, less, find, 인터프리터 등을 sudo로 허용 → 그 안에서 root 쉘 실행 가능명령 한정 시에도 쉘 탈출 가능 여부 확인 (GTFOBins)
와일드카드 규칙/usr/bin/cat /var/log/* → ../로 다른 파일 지정 가능와일드카드 지양
사용자 쓰기 가능 스크립트 허용허용된 스크립트 내용을 바꿔 임의 명령 실행허용 대상은 root 소유·쓰기 불가
root 비밀번호 공유 + su누가 했는지 불명확sudo 사용, root 원격 로그인 금지
env_keep에 위험 변수PATH·LD_PRELOAD 전달 (9편)기본 설정 유지

7. SOC / 보안관제 활용

7-1. 로그 검색

# sudo로 실행된 명령 목록 (실행자별)
sudo grep 'COMMAND=' /var/log/secure \
  | sed -E 's/.*sudo\[[0-9]+\]: +([^ ]+) : .*COMMAND=(.*)/\1 \2/' \
  | sort | uniq -c | sort -rn | head

# 실패·거부
sudo grep -E 'NOT in sudoers|incorrect password|FAILED SU' /var/log/secure

# 쉘을 sudo로 연 경우
sudo grep -E 'COMMAND=.*(/bash|/sh|su -|-i$)' /var/log/secure

# sudoers 변경 감사
sudo ausearch -k sudoers_change -i | tail

7-2. 감사 규칙

# /etc/audit/rules.d/priv.rules
-w /etc/sudoers -p wa -k sudoers_change
-w /etc/sudoers.d/ -p wa -k sudoers_change
# root 권한으로 실행된 명령을 원래 사용자(auid)와 함께 기록
-a always,exit -F arch=b64 -S execve -F euid=0 -F auid>=1000 -F auid!=unset -k root_exec

7-3. 분석 흐름

[Alert]   SIEM: 'user NOT in sudoers' 5회 (계정 intern01, 23:10~23:12)
   ↓
[맥락]    intern01 은 평소 sudo를 쓰지 않는 계정 / 23:08 SSH 로그인, 출발지 해외 IP
   ↓
[IOC]     출발지 IP, 시도한 COMMAND (id, bash, cat /etc/shadow)
   ↓
[추가 확인] 이후 su 시도(FAILED SU), SUID 파일 탐색(find -perm -4000) audit 기록
   ↓
[판단]    탈취 계정으로 권한 상승 경로 탐색 중 → 침해 의심
   ↓
[Response] 세션 종료·계정 잠금, 출발지 차단, 비밀번호 재설정, 같은 IP의 다른 서버 접속 조회

8. 핵심 정리

  • su는 대상 계정 비밀번호 로 쉘 전체를 얻고, sudo는 본인 비밀번호 로 허용된 명령만 실행한다.
  • sudo는 명령마다 /var/log/secure(Ubuntu auth.log)에 USER, COMMAND를 남긴다. su는 세션 시작만 남는다.
  • sudoers는 visudo로만 수정하고, 규칙은 /etc/sudoers.d/로 분리한다.
  • NOPASSWD: ALL, 쉘 탈출 가능한 명령 허용, 와일드카드, 사용자 쓰기 가능 스크립트 허용은 위험 설정이다.
  • user NOT in sudoers, incorrect password attempts, FAILED SU는 권한 상승 시도 의 신호다.
  • su 이후 명령은 auditd execve + auid 로 원래 사용자에게 연결한다.

9. 다음 글

다음 글 「20. 최소 권한 원칙」 은 Part 2의 마무리다. 11~19편에서 다룬 파일 권한, 소유권, 계정, sudo를 최소 권한 원칙(Least Privilege) 이라는 하나의 기준으로 묶고, 서비스 계정·systemd·SSH까지 적용하는 점검 체크리스트를 만든다.


참고 자료

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

0개의 댓글