파일 · 권한 · 사용자 관리 36 / 50 · Part 4. 사용자와 그룹 관리
실습 환경: Rocky Linux 9.8 · Ubuntu 24.04.5 (Docker 격리 컨테이너, 테스트 계정analyst)
기초편 연계: 「리눅스 시스템 기초」 18. Linux 사용자와 그룹
35편에서 useradd로 계정을 만들었다. 이번 글은 기존 계정을 변경 하는 usermod다.
usermod에는 실무에서 가장 자주 사고를 내는 함정이 하나 있다. 보조 그룹을 추가할 때 -aG의 -a를 빠뜨리면 기존 보조 그룹이 전부 교체(삭제) 된다. 관리자를 sudo 그룹에서 실수로 빼 버려 서버 관리 권한을 잃는 사고가 여기서 나온다.
이번 글에서는 이 함정을 실제로 재현하고, 계정을 삭제하지 않고 안전하게 비활성화 하는 방법(셸 변경 + 잠금)을 실습한다.
| 옵션 | 의미 |
|---|---|
-aG group | 보조 그룹 추가 (기존 유지) |
-G g1,g2 | 보조 그룹 교체 (나열한 것만 남김) |
-s SHELL | 로그인 셸 변경 |
-L / -U | 계정 잠금 / 해제 |
-d DIR -m | 홈 디렉터리 변경 + 기존 내용 이동 |
-u UID | UID 변경 |
-e YYYY-MM-DD | 만료일 |
-c "설명" | GECOS |
이것이 핵심이다.
usermod -aG ops user: user의 보조 그룹에 ops를 추가 한다.usermod -G ops user: user의 보조 그룹을 ops 하나로 교체 한다. 기존 보조 그룹은 모두 사라진다.-G는 "이 목록이 전부"라는 의미다. 그래서 보조 그룹을 추가할 때는 항상 -aG를 쓴다.
계정을 없앨 때 바로 userdel(37편)하면 파일 소유권 문제와 감사 이력 손실이 생긴다. 그래서 실무에서는 먼저 비활성화 를 선호한다.
usermod -L user — 비밀번호 잠금usermod -s /usr/sbin/nologin user — 로그인 셸 차단
usermod는 useradd가 만든 여러 파일을 수정한다. 그룹 변경은 /etc/group(과 gshadow), 셸·홈 변경은 /etc/passwd, 잠금은 /etc/shadow를 바꾼다.
-G가 위험한 이유는 이 옵션이 "설정(set)"이지 "추가(append)"가 아니기 때문이다. 커널이나 셸이 막아 주지 않으므로, usermod -G newgroup admin을 실행하면 admin의 wheel·sudo 같은 기존 보조 그룹이 조용히 사라진다. 명령은 성공으로 끝나고, 문제는 다음 로그인 때야 드러난다.
UID 변경(-u)도 주의가 필요하다. UID를 바꾸면 홈 디렉터리 안의 파일 소유권은 usermod가 자동으로 갱신하지만, 다른 위치의 파일 은 옛 UID로 남는다. 그 파일들은 find -uid 옛UID로 찾아 별도로 chown해야 한다.
edituser는team보조 그룹을 가진 계정이다. root 권한 실습이다.
# 1) 변경 전 상태
id edituser
# 2) 보조 그룹 추가 — 올바른 방법
usermod -aG ops edituser && id edituser # team, ops 둘 다
# 3) -G 만 쓰면 기존 보조 그룹 교체 (함정)
usermod -G team edituser && id edituser # ops 사라짐!
usermod -aG ops edituser && id edituser # 복구
# 4) 셸 변경으로 비활성화
usermod -s /usr/sbin/nologin edituser && getent passwd edituser
# 5) 계정 잠금
usermod -L edituser
passwd -S edituser 2>/dev/null || getent shadow edituser | cut -d: -f1,2
# 6) 홈 디렉터리 이동
usermod -d /opt/edituser -m edituser && getent passwd edituser && ls -ld /opt/edituser

텍스트 원본(실제 출력):
[root@rocky9-lab ~]# echo "=== 변경 전 ==="
=== 변경 전 ===
[root@rocky9-lab ~]# id edituser
uid=1001(edituser) gid=1003(edituser) groups=1003(edituser),1001(team)
[root@rocky9-lab ~]# getent passwd edituser
edituser:x:1001:1003::/home/edituser:/bin/bash
[root@rocky9-lab ~]# echo "=== 보조 그룹 추가: -aG (올바름) ==="
=== 보조 그룹 추가: -aG (올바름) ===
[root@rocky9-lab ~]# usermod -aG ops edituser && id edituser
uid=1001(edituser) gid=1003(edituser) groups=1003(edituser),1001(team),1002(ops)
[root@rocky9-lab ~]# echo "=== -G 만 쓰면? (기존 보조 그룹 교체 위험) ==="
=== -G 만 쓰면? (기존 보조 그룹 교체 위험) ===
[root@rocky9-lab ~]# usermod -G team edituser && id edituser
uid=1001(edituser) gid=1003(edituser) groups=1003(edituser),1001(team)
[root@rocky9-lab ~]# echo " ↑ ops 가 사라짐! 다시 복구"
↑ ops 가 사라짐! 다시 복구
[root@rocky9-lab ~]# usermod -aG ops edituser && id edituser
uid=1001(edituser) gid=1003(edituser) groups=1003(edituser),1001(team),1002(ops)
[root@rocky9-lab ~]# echo "=== 셸 변경으로 계정 비활성화 ==="
=== 셸 변경으로 계정 비활성화 ===
[root@rocky9-lab ~]# usermod -s /usr/sbin/nologin edituser && getent passwd edituser
edituser:x:1001:1003::/home/edituser:/usr/sbin/nologin
[root@rocky9-lab ~]# echo "=== 계정 잠금 ==="
=== 계정 잠금 ===
[root@rocky9-lab ~]# usermod -L edituser && passwd -S edituser 2>/dev/null || getent shadow edituser | cut -d: -f1,2
edituser LK 2026-09-24 0 99999 7 -1 (Password locked.)
[root@rocky9-lab ~]# echo "=== 홈 이동 ==="
=== 홈 이동 ===
[root@rocky9-lab ~]# usermod -d /opt/edituser -m edituser && getent passwd edituser && ls -ld /opt/edituser
edituser:x:1001:1003::/opt/edituser:/usr/sbin/nologin
drwx------ 2 edituser edituser 4096 Sep 24 14:52 /opt/edituser
| 출력 | 해석 |
|---|---|
시작 groups=...(edituser),(team) | 기본 그룹 + team |
usermod -aG ops → ...,team,ops | ops 추가 (team 유지) |
usermod -G team → ...,team | ops 사라짐. -G는 교체 |
usermod -aG ops → ...,team,ops | 다시 추가해 복구 |
usermod -s nologin → 셸 /usr/sbin/nologin | 로그인 셸 차단 |
edituser LK ... (passwd -S) | LK = Locked (비밀번호 잠금) |
usermod -d /opt/edituser -m → 홈 /opt/edituser | 홈 이동 + 내용 이전 |
세 번째~네 번째 줄이 이번 실습의 핵심이다. -G team한 번으로 ops가 사라졌다가 -aG ops로 복구됐다. 실제 서버에서 이것이 sudo/wheel 그룹이었다면 관리 권한 상실 사고다.
| 주제 | 내용 |
|---|---|
-aG 강제 | 그룹 추가는 항상 -aG. 스크립트·문서에도 명시 |
| 비활성화 우선 | 퇴사·의심 계정은 삭제 전 잠금 + nologin으로 증거 보존 |
| UID 변경 신중 | 홈 밖 파일 소유권은 수동 갱신 필요 |
| 만료 정책 | 임시·협력사 계정은 -e로 만료일 지정 |
| 셸 변경 감사 | 서비스 계정 셸이 nologin→bash로 바뀌면 이상 신호 |
공격자 관점: 공격자가 서비스 계정의 셸을 nologin에서 bash로 바꾸는 것(usermod -s /bin/bash)은 로그인 가능한 발판을 만드는 지속성 기법이다. 셸 변경도 감사 대상이다.
[Detection] auditd/로그: usermod 실행, /etc/passwd·group·shadow 변경
grep usermod /var/log/secure # Rocky
grep usermod /var/log/auth.log # Ubuntu
↓
[이상 신호] 서비스 계정 셸 nologin→bash / 계정의 wheel·sudo 편입 / 잠금 해제(-U)
↓
[Evidence] 변경 대상·시각(ctime), 변경 주체(sudo 로그, 49편)
↓
[Response] 무단 변경 원복, 계정 잠금, 침입 경로 조사
| 관점 | 내용 |
|---|---|
| IOC | 서비스 계정의 로그인 셸 부여, 관리자 그룹 편입, 계정 잠금 해제 |
| Detection | usermod·gpasswd 실행을 auditd로 감시 |
| 비활성화 기록 | 계정 비활성화(잠금+nologin)는 대응 조치로 로그에 남긴다 |
| 실수 | 결과 | 예방 |
|---|---|---|
usermod -G로 그룹 추가 시도 | 기존 보조 그룹 삭제 | 항상 -aG |
관리자 계정에 -G 사용 | sudo/wheel 상실 | -aG, 변경 전 id 확인 |
| UID 변경 후 홈 밖 파일 방치 | 옛 UID 소유 파일 잔존 | find -uid로 갱신 |
| 계정 삭제 먼저 | 파일 소유권·증거 손실 | 잠금·nologin 먼저 |
-d 만 쓰고 -m 누락 | 홈 경로만 바뀌고 내용 안 옮겨짐 | -d ... -m |
[ ] -aG 와 -G 의 차이를 재현했다
[ ] -G 로 기존 보조 그룹이 사라지는 것을 확인했다
[ ] usermod -s nologin 으로 로그인을 차단했다
[ ] usermod -L 로 계정을 잠갔다 (passwd -S 로 LK 확인)
[ ] usermod -d -m 으로 홈을 이동했다
[ ] 삭제 대신 비활성화가 나은 이유를 설명할 수 있다
-aG. -G는 기존 보조 그룹을 교체(삭제)한다.usermod -L(잠금) + usermod -s nologin(셸 차단) 2단계다.find -uid로 수동 갱신한다.usermod·gpasswd 실행을 로그로 감시한다.다음 글 「37. userdel과 계정 삭제」 에서는 계정 삭제 시 남는 파일 소유권 문제 를 다룬다. 삭제된 계정의 파일이 UID 숫자로 남고, 같은 UID로 새 계정이 생기면 그 파일들을 물려받는 위험을 실제로 재현한다.
-S, -l — https://man7.org/linux/man-pages/man1/passwd.1.html