리눅스 시스템 기초 · 입문편 — 본문의 "N편"은 입문 과정 번호다. 번호별 글과 전체 250편 구성은 통합 로드맵에서 확인할 수 있다.
리눅스 시스템 기초 18 / 50 · Part 2. 파일·명령어·권한
실습 환경: Rocky Linux 9 (10.0.0.200) · 비교: Ubuntu 22.04
이전 글: 17. chown과 파일 소유권
🔗 심화 시리즈 — 「파일 · 권한 · 사용자 관리」
이 주제를 더 깊게 다룬 실무형 보안 시리즈: 31. Linux 사용자 계정 구조 · 32. /etc/passwd 분석 · 33. /etc/shadow 분석 · 34. /etc/group 분석
15~17편에서 권한과 소유권을 다뤘다. 권한 검사의 주체는 결국 계정(UID)과 그룹(GID) 이다. 이번 글은 Linux가 계정 정보를 어디에, 어떤 형식으로 저장하는지 정리한다.
보안관제에서 계정은 가장 중요한 분석 대상 중 하나다.
| 파일 | 내용 | 권한 (Rocky 9) |
|---|---|---|
/etc/passwd | 계정명, UID, GID, 홈, 쉘 | 644 누구나 읽기 |
/etc/shadow | 비밀번호 해시, 만료 정책 | 000 (root만) |
/etc/group | 그룹명, GID, 보조 구성원 | 644 |
/etc/gshadow | 그룹 비밀번호, 그룹 관리자 | 000 |
/etc/login.defs | UID 범위, 비밀번호 기본 정책 | 644 |
/etc/skel/ | 새 계정 홈에 복사할 기본 파일 |
예전에는 /etc/passwd에 해시를 저장했지만, 누구나 읽을 수 있는 파일이라 해시를 root만 읽는 /etc/shadow로 분리 했다. passwd의 두 번째 필드 x는 "해시는 shadow에 있음"을 뜻한다.
roror:x:1000:1000:roror:/home/roror:/bin/bash
① ② ③ ④ ⑤ ⑥ ⑦
| 번호 | 필드 | 보안 확인 포인트 |
|---|---|---|
| ① | 계정명 | 정상 계정과 비슷한 이름(r00t, admin1) |
| ② | x | 이 자리에 해시나 빈 값이 있으면 이상 |
| ③ | UID | root 외 UID 0 은 백도어 |
| ④ | 기본 GID | |
| ⑤ | 설명 | |
| ⑥ | 홈 | 서비스 계정 홈이 /tmp 등 |
| ⑦ | 로그인 쉘 | 서비스 계정에 /bin/bash (3편) |
roror:$6$Qm1a...$Xk9...:20354:0:99999:7:::
① ② ③ ④ ⑤ ⑥⑦⑧
| 번호 | 필드 | 의미 |
|---|---|---|
| ② | 해시 | $알고리즘$salt$해시값 |
| ③ | 마지막 변경일 | 1970-01-01부터의 일수 |
| ④ / ⑤ | 최소 / 최대 사용 기간 | 99999 = 사실상 만료 없음 |
| ⑥ | 경고 기간 | 만료 며칠 전 경고 |
| ⑦ | 비활성 기간 | 만료 후 잠기기까지 |
| ⑧ | 계정 만료일 |
| 해시 자리 값 | 의미 |
|---|---|
$6$... | SHA-512 crypt (Rocky 9 기본) |
$y$... | yescrypt (Ubuntu 22.04 기본) |
! 또는 !!로 시작 | 잠김 / 비밀번호 미설정 |
* | 비밀번호 로그인 불가 (서비스 계정) |
| 빈 값 | 비밀번호 없이 로그인 가능 — 즉시 조치 |
| 범위 | 용도 |
|---|---|
0 | root — 권한 검사의 기준. 반드시 하나 |
1 ~ 999 | 시스템·서비스 계정 (RHEL 계열은 201~999 동적 할당) |
1000 ~ | 일반 사용자 |
| 구분 | 저장 위치 | 의미 |
|---|---|---|
| 기본 그룹 (primary) | passwd ④ | 새 파일의 그룹 |
| 보조 그룹 (supplementary) | group 네 번째 필드 | 추가로 속한 그룹 — 권한 검사에 모두 사용 |
관리자 권한은 보조 그룹으로 주어지는 경우가 많다. RHEL 계열은 wheel, Ubuntu는 sudo 그룹이 sudo 사용 권한을 가진다(19편).

로그인 과정에서 계정 파일은 다음처럼 쓰인다.
sshd / login
↓ PAM (인증 모듈)
passwd 에서 계정 존재·쉘 확인 → shadow 에서 해시 비교 → 만료·잠금 확인
↓ 성공
UID·GID·보조 그룹으로 프로세스 생성 → 홈 디렉터리에서 로그인 쉘 실행
↓
/var/log/secure 에 인증 결과 기록
useradd, usermod, passwd 같은 명령은 이 파일들을 안전하게 수정(잠금 → 수정 → 교체)하고, 그 행위를 /var/log/secure(Ubuntu는 auth.log)와 audit 로그 에 남긴다.
# 1) 계정 정보 조회
id roror
getent passwd roror
getent group wheel
sudo getent shadow roror | cut -d: -f1,3-8 # 해시는 출력하지 않음
sudo chage -l roror # 만료 정책을 읽기 쉽게
# 2) UID 범위 설정
grep -E '^(UID|GID|SYS_UID|SYS_GID)_(MIN|MAX)' /etc/login.defs
# 3) 계정 생성 → 그룹 추가 → 잠금 → 삭제
sudo useradd -m -s /bin/bash lab18user
sudo passwd lab18user
sudo usermod -aG wheel lab18user # -a 없이 -G만 쓰면 기존 보조 그룹이 사라짐
id lab18user
sudo usermod -L lab18user # 잠금 (해시 앞에 !)
sudo grep lab18user /etc/shadow | cut -c1-20
sudo userdel -r lab18user
# 4) 계정 변경 로그
sudo grep -E 'useradd|usermod|userdel|groupadd|passwd' /var/log/secure | tail
sudo ausearch -m ADD_USER,DEL_USER,USER_MGMT,ADD_GROUP -i | tail -20
# 5) 로그인 기록
lastlog | grep -v 'Never'
아래 출력은 형식 설명용 예시다.
① /var/log/secure의 계정 생성 로그
Sep 23 11:50:12 rocky useradd[5310]: new group: name=lab18user, GID=1003
Sep 23 11:50:12 rocky useradd[5310]: new user: name=lab18user, UID=1003, GID=1003, home=/home/lab18user, shell=/bin/bash, from=/dev/pts/0
Sep 23 11:50:40 rocky usermod[5322]: add 'lab18user' to group 'wheel'
Sep 23 11:50:40 rocky usermod[5322]: add 'lab18user' to shadow group 'wheel'
| 로그 | 관제 해석 |
|---|---|
new user: ... shell=/bin/bash | 로그인 가능한 새 계정 |
from=/dev/pts/0 | 원격 터미널(SSH 세션)에서 실행 |
add ... to group 'wheel' | 관리자 권한 부여 — 변경 승인 여부 확인 필요 |
② chage -l
Last password change : Sep 23, 2026
Password expires : never
Account expires : never
never가 많으면 비밀번호 주기 정책이 없는 상태다. 조직 정책(주요정보통신기반시설 가이드 등)에 맞춰 점검 항목이 된다.
| 공격 / 취약 설정 | 흔적 | 확인 명령 |
|---|---|---|
| UID 0 백도어 계정 | passwd에 UID 0이 둘 이상 | awk -F: '$3==0' /etc/passwd |
| 빈 비밀번호 | shadow 해시 필드 공백 | sudo awk -F: '$2==""' /etc/shadow |
| 관리자 그룹 추가 | group의 wheel/sudo 구성원 변화 | getent group wheel sudo |
| 서비스 계정 로그인 | 쉘이 /bin/bash | 3편 점검 |
| passwd 직접 편집 | useradd 로그 없이 계정 추가 | audit -w /etc/passwd -p wa (5편) |
| 휴면 계정 악용 | 오래 안 쓰던 계정이 갑자기 로그인 | lastlog, 로그인 로그 |
| 해시 탈취 | shadow 읽기 | shadow 권한, audit shadow_access |
/etc/passwd를 편집기로 직접 수정하면 useradd 로그가 남지 않는다. 그래서 파일 감시(auditd -w, FIM)와 명령 로그를 함께 봐야 한다.
echo "== UID 0 =="; awk -F: '$3==0 {print $1}' /etc/passwd
echo "== 빈 비밀번호 =="; sudo awk -F: '$2=="" {print $1}' /etc/shadow
echo "== 로그인 가능 계정 =="; awk -F: '$7 !~ /(nologin|false)$/ {print $1, $3, $7}' /etc/passwd
echo "== 관리자 그룹 =="; getent group wheel sudo 2>/dev/null
echo "== 만료 없는 계정 =="; sudo awk -F: '$2 ~ /^\$/ && ($5=="" || $5==99999) {print $1}' /etc/shadow
echo "== 최근 7일 계정 변경 =="; sudo grep -hE 'new user|delete user|add .* to group' /var/log/secure* 2>/dev/null | tail
# /etc/audit/rules.d/identity.rules
-w /etc/passwd -p wa -k identity
-w /etc/shadow -p wa -k identity
-w /etc/group -p wa -k identity
-w /etc/gshadow -p wa -k identity
[Alert] SIEM: usermod — 'svcbackup' 계정 wheel 그룹 추가 (02:47)
↓
[확인] 변경 요청(티켓) 없음 / svcbackup 은 원래 nologin 서비스 계정
/etc/passwd → 쉘이 /bin/bash 로 변경됨 (audit identity)
↓
[IOC] 변경 직전 로그인 세션: 02:40 SSH Accepted password for admin from 198.51.100.23
↓
[Root Cause] admin 계정 탈취 → 서비스 계정을 관리자 백도어로 전환
↓
[Response] svcbackup 잠금·쉘 원복·그룹 제거, admin 비밀번호 변경·세션 종료, 출발지 IP 차단
/etc/passwd(정보), /etc/shadow(해시·만료), /etc/group(그룹)에 저장된다.x는 해시가 shadow에 있다는 뜻이다. shadow는 root만 읽을 수 있어야 한다.$6$, $y$)과 상태(! 잠김, * 로그인 불가, 빈 값 = 무비밀번호)를 판단한다.usermod -aG의 -a를 빠뜨리지 않는다./var/log/secure와 audit 로그에 남는다. 직접 편집은 명령 로그가 없으므로 파일 감시가 필요 하다.다음 글 「19. sudo와 su」 에서는 일반 계정이 root 권한을 얻는 두 가지 방법을 비교한다. sudoers 문법, wheel 그룹, 그리고 /var/log/secure에 남는 sudo·su 로그를 읽고 누가 언제 어떤 명령을 root로 실행했는지 추적하는 방법을 다룬다.