파일 · 권한 · 사용자 관리 42 / 50 · Part 5. 권한 상승과 Linux 보안
실습 환경: Rocky Linux 9.8 · Ubuntu 24.04.5 (Docker 격리 컨테이너, 테스트 계정 analyst)
기초편 연계: 「리눅스 시스템 기초」 19. sudo와 su

1. 들어가며

41편에서 sudo가 sudoers 규칙에 따라 명령을 허용한다고 했다. 이번 글에서는 그 규칙 파일 /etc/sudoers를 다룬다.

두 가지가 핵심이다. 첫째, sudoers 문법 — "누가, 어디서, 누구로, 어떤 명령을" 실행할 수 있는지 정의하는 형식. 둘째, visudo — sudoers를 편집할 때 반드시 써야 하는 도구다. sudoers에 문법 오류가 있으면 sudo 전체가 동작하지 않아 root 접근을 잃을 수 있는데, visudo는 저장 전에 문법을 검사해 이 사고를 막는다.

최소 권한 원칙에 따라 특정 명령만 허용 하는 규칙을 실습으로 작성한다.


2. 핵심 개념

2-1. sudoers 문법

사용자  호스트=(실행계정:실행그룹)  [옵션:]  명령
요소의미예
사용자누구에게 (%는 그룹)deploy, %webops
호스트어느 호스트에서ALL
실행계정누구 권한으로(root), (ALL)
옵션NOPASSWD: 등NOPASSWD:
명령허용 명령(전체 경로)/usr/bin/systemctl restart httpd

예:

deploy  ALL=(root) NOPASSWD: /usr/bin/systemctl restart httpd
%webops ALL=(root) /usr/bin/journalctl

2-2. sudoers.d

개별 규칙은 /etc/sudoers를 직접 고치기보다 /etc/sudoers.d/ 아래 파일로 분리하는 것이 관리하기 좋다. 파일 권한은 440이어야 한다.

2-3. visudo

sudoers 편집은 반드시 visudo 로 한다. visudo는:

  • 파일을 잠가 동시 편집을 방지하고,
  • 저장 시 문법을 검사 해 오류가 있으면 저장을 막는다.

visudo -c는 검사만, visudo -c -f 파일은 특정 파일을 검사한다.


3. 동작 원리

sudoers 문법과 visudo

sudo가 실행되면 /etc/sudoers와 /etc/sudoers.d/*를 위에서부터 읽어, 실행자·명령에 맞는 마지막 일치 규칙 을 적용한다. 그래서 규칙 순서가 중요하다.

visudo가 필수인 이유는 sudoers의 특성 때문이다. 이 파일에 문법 오류가 하나라도 있으면 sudo가 파일 전체를 거부해 아무도 sudo를 쓸 수 없게 된다. root 비밀번호를 설정하지 않은 시스템(Ubuntu 기본)에서는 이것이 곧 관리 권한 완전 상실 이다. visudo는 저장 직전 검사로 이 치명적 사고를 예방한다.

최소 권한 설계의 핵심은 (ALL) ALL을 피하고 필요한 명령만 전체 경로로 지정하는 것이다. 단, 명령 경로만 제한한다고 안전한 것은 아니다. 허용한 명령이 셸 탈출이나 파일 읽기가 가능하면 권한 상승으로 이어진다(43편).


4. 명령어 실습

root 권한 실습. deploy 사용자와 webops 그룹에 제한된 sudo 규칙을 부여했다.

# 1) sudoers.d 규칙 확인
cat /etc/sudoers.d/deploy

# 2) 문법 검사 (정상)
visudo -c -f /etc/sudoers.d/deploy

# 3) 잘못된 문법은 저장 거부 (NOPASWD 오타)
echo 'baduser ALL=(ALL) NOPASWD: ALL' > /tmp/badsudoers
visudo -c -f /tmp/badsudoers

# 4) deploy 의 권한 확인
sudo -l -U deploy

5. 실행 결과

실제 실행 결과 — Rocky Linux 9.8 · root@rocky9-lab — sudoers 문법과 visudo

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

[root@rocky9-lab ~]# echo "=== sudoers 문법: 사용자 호스트=(실행계정) 명령 ==="
=== sudoers 문법: 사용자 호스트=(실행계정) 명령 ===
[root@rocky9-lab ~]# cat /etc/sudoers.d/deploy
deploy ALL=(root) NOPASSWD: /usr/bin/systemctl restart httpd, /usr/bin/systemctl status httpd
%webops ALL=(root) /usr/bin/journalctl
[root@rocky9-lab ~]# echo "=== visudo -c : 문법 검사 ==="
=== visudo -c : 문법 검사 ===
[root@rocky9-lab ~]# visudo -c -f /etc/sudoers.d/deploy
/etc/sudoers.d/deploy: parsed OK
[root@rocky9-lab ~]# echo "=== 잘못된 문법은 저장 거부 (시뮬레이션) ==="
=== 잘못된 문법은 저장 거부 (시뮬레이션) ===
[root@rocky9-lab ~]# echo 'baduser ALL=(ALL) NOPASWD: ALL' > /tmp/badsudoers
[root@rocky9-lab ~]# visudo -c -f /tmp/badsudoers 2>&1 || echo "→ visudo 가 오류를 잡아냄"
/tmp/badsudoers:1:31: syntax error
baduser ALL=(ALL) NOPASWD: ALL
                              ^
→ visudo 가 오류를 잡아냄
[root@rocky9-lab ~]# echo "=== deploy 의 권한 확인 ==="
=== deploy 의 권한 확인 ===
[root@rocky9-lab ~]# sudo -l -U deploy 2>/dev/null | tail -4

User deploy may run the following commands on rocky9-lab:
    (root) NOPASSWD: /usr/bin/systemctl restart httpd, /usr/bin/systemctl status httpd
    (root) /usr/bin/journalctl

6. 결과 해석

출력해석
deploy ALL=(root) NOPASSWD: /usr/bin/systemctl restart httpd, ... status httpddeploy는 httpd 재시작·상태만 비밀번호 없이
%webops ALL=(root) /usr/bin/journalctlwebops 그룹은 journalctl(비밀번호 필요)
visudo -c -f deploy → parsed OK문법 정상
badsudoers:1:31: syntax errorNOPASWD 오타를 위치까지 지목
→ visudo 가 오류를 잡아냄저장 전 검사로 사고 예방
sudo -l -U deploy → 허용 명령 목록deploy가 실제로 쓸 수 있는 명령 확인

syntax error가 위치(1:31)와 ^ 표시로 정확히 지목된 것이 핵심이다. visudo 없이 직접 편집해 이 오타를 저장했다면 sudo 전체가 멈췄을 것이다.


7. 보안 관점

원칙방법
최소 권한(ALL) ALL 대신 필요한 명령만 전체 경로
명령 제한의 한계허용 명령이 셸 탈출 가능하면 무의미(43편)
secure_pathsudo 실행 시 PATH 고정(secure_path)으로 PATH 하이재킹 방지(04편)
NOPASSWD 신중자동화에 필요한 최소 명령만. 범용 명령 금지
sudoers.d 권한440, root 소유
정기 검토sudo -l -U user로 사용자별 권한 감사

위험 패턴: user ALL=(ALL) NOPASSWD: ALL은 비밀번호 없이 모든 것을 허용하는 사실상 무제한 root다. 이런 규칙이 있는지 점검한다.


8. 보안관제 관점

[점검]   sudoers 전체 규칙 감사
   sudo -l -U <user>                        # 사용자별 권한
   grep -rvE '^#|^$' /etc/sudoers /etc/sudoers.d/    # 규칙 나열
   visudo -c                                # 문법 무결성
     ↓
[이상]   NOPASSWD: ALL / 셸·에디터·인터프리터 허용 / 광범위 와일드카드
     ↓
[Evidence] sudoers 파일 ctime, 변경 주체(로그), 규칙 추가 시각
     ↓
[Detection] /etc/sudoers.d/ 파일 추가·변경을 FIM 으로 감시
     ↓
[Response] 과도한 규칙 축소, 무단 규칙 제거, 경위 조사
관점내용
IOC공격자가 /etc/sudoers.d/에 자기 규칙 파일을 추가하는 것은 흔한 지속성 기법
Detectionsudoers.d 디렉터리 변경을 FIM으로 실시간 감시
감사사용자별 sudo -l을 주기적으로 검토(48편)

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

실수결과예방
sudoers 직접 편집문법 오류로 sudo 잠김반드시 visudo
(ALL) ALL 남발사실상 무제한 root필요한 명령만
명령 경로만 제한하고 안심셸 탈출로 우회(43편)안전한 명령만 허용
sudoers.d 권한 644무시되거나 경고440
secure_path 미설정PATH 하이재킹Defaults secure_path

10. 실습 체크리스트

[ ] sudoers 문법(사용자 호스트=(실행계정) 명령)을 해석했다
[ ] visudo -c 로 문법을 검사했다
[ ] 오타가 저장 거부되는 것을 확인했다
[ ] sudoers.d 로 규칙을 분리했다
[ ] sudo -l -U 로 사용자 권한을 감사했다
[ ] NOPASSWD: ALL 이 왜 위험한지 설명할 수 있다

11. 핵심 정리

  • sudoers 문법은 사용자 호스트=(실행계정) [옵션:] 명령 이다.
  • 편집은 반드시 visudo — 문법 오류를 저장 전에 잡아 sudo 잠김 사고를 막는다.
  • 최소 권한: (ALL) ALL 대신 필요한 명령만 전체 경로로 지정한다.
  • 개별 규칙은 /etc/sudoers.d/(권한 440)로 분리 관리한다.
  • 명령 경로 제한만으로는 부족하다. 셸 탈출 가능한 명령은 위험(43편).
  • sudoers.d 변경을 FIM으로 감시하고 사용자별 권한을 정기 감사한다.

12. 다음 편 예고

다음 글 「43. sudo 잘못된 설정과 권한 상승」 에서는 NOPASSWD로 허용된 find 하나가 어떻게 완전한 root 권한으로 이어지는지(GTFOBins) 실제로 재현한다. "특정 명령만 허용"이 왜 안전을 보장하지 못하는지 확인한다.


참고 자료


시리즈 이동

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

0개의 댓글