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

1. 들어가며

35편에서 useradd로 계정을 만들었다. 이번 글은 기존 계정을 변경 하는 usermod다.

usermod에는 실무에서 가장 자주 사고를 내는 함정이 하나 있다. 보조 그룹을 추가할 때 -aG의 -a를 빠뜨리면 기존 보조 그룹이 전부 교체(삭제) 된다. 관리자를 sudo 그룹에서 실수로 빼 버려 서버 관리 권한을 잃는 사고가 여기서 나온다.

이번 글에서는 이 함정을 실제로 재현하고, 계정을 삭제하지 않고 안전하게 비활성화 하는 방법(셸 변경 + 잠금)을 실습한다.


2. 핵심 개념

2-1. 주요 옵션

옵션의미
-aG group보조 그룹 추가 (기존 유지)
-G g1,g2보조 그룹 교체 (나열한 것만 남김)
-s SHELL로그인 셸 변경
-L / -U계정 잠금 / 해제
-d DIR -m홈 디렉터리 변경 + 기존 내용 이동
-u UIDUID 변경
-e YYYY-MM-DD만료일
-c "설명"GECOS

2-2. -aG vs -G

이것이 핵심이다.

  • usermod -aG ops user: user의 보조 그룹에 ops를 추가 한다.
  • usermod -G ops user: user의 보조 그룹을 ops 하나로 교체 한다. 기존 보조 그룹은 모두 사라진다.

-G는 "이 목록이 전부"라는 의미다. 그래서 보조 그룹을 추가할 때는 항상 -aG를 쓴다.

2-3. 삭제 대신 비활성화

계정을 없앨 때 바로 userdel(37편)하면 파일 소유권 문제와 감사 이력 손실이 생긴다. 그래서 실무에서는 먼저 비활성화 를 선호한다.

  1. usermod -L user — 비밀번호 잠금
  2. usermod -s /usr/sbin/nologin user — 로그인 셸 차단

3. 동작 원리

usermod — 기존 계정 변경의 함정

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해야 한다.


4. 명령어 실습

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

5. 실행 결과

실제 실행 결과 — Rocky Linux 9.8 · root@rocky9-lab — usermod 와 -aG 함정

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

[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

6. 결과 해석

출력해석
시작 groups=...(edituser),(team)기본 그룹 + team
usermod -aG ops → ...,team,opsops 추가 (team 유지)
usermod -G team → ...,teamops 사라짐. -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 그룹이었다면 관리 권한 상실 사고다.


7. 보안 관점

주제내용
-aG 강제그룹 추가는 항상 -aG. 스크립트·문서에도 명시
비활성화 우선퇴사·의심 계정은 삭제 전 잠금 + nologin으로 증거 보존
UID 변경 신중홈 밖 파일 소유권은 수동 갱신 필요
만료 정책임시·협력사 계정은 -e로 만료일 지정
셸 변경 감사서비스 계정 셸이 nologin→bash로 바뀌면 이상 신호

공격자 관점: 공격자가 서비스 계정의 셸을 nologin에서 bash로 바꾸는 것(usermod -s /bin/bash)은 로그인 가능한 발판을 만드는 지속성 기법이다. 셸 변경도 감사 대상이다.


8. 보안관제 관점

[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서비스 계정의 로그인 셸 부여, 관리자 그룹 편입, 계정 잠금 해제
Detectionusermod·gpasswd 실행을 auditd로 감시
비활성화 기록계정 비활성화(잠금+nologin)는 대응 조치로 로그에 남긴다

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

실수결과예방
usermod -G로 그룹 추가 시도기존 보조 그룹 삭제항상 -aG
관리자 계정에 -G 사용sudo/wheel 상실-aG, 변경 전 id 확인
UID 변경 후 홈 밖 파일 방치옛 UID 소유 파일 잔존find -uid로 갱신
계정 삭제 먼저파일 소유권·증거 손실잠금·nologin 먼저
-d 만 쓰고 -m 누락홈 경로만 바뀌고 내용 안 옮겨짐-d ... -m

10. 실습 체크리스트

[ ] -aG 와 -G 의 차이를 재현했다
[ ] -G 로 기존 보조 그룹이 사라지는 것을 확인했다
[ ] usermod -s nologin 으로 로그인을 차단했다
[ ] usermod -L 로 계정을 잠갔다 (passwd -S 로 LK 확인)
[ ] usermod -d -m 으로 홈을 이동했다
[ ] 삭제 대신 비활성화가 나은 이유를 설명할 수 있다

11. 핵심 정리

  • 보조 그룹 추가는 항상 -aG. -G는 기존 보조 그룹을 교체(삭제)한다.
  • 계정 비활성화는 usermod -L(잠금) + usermod -s nologin(셸 차단) 2단계다.
  • 삭제보다 비활성화가 파일 소유권·감사 이력을 보존한다.
  • UID 변경 시 홈 밖 파일 소유권은 find -uid로 수동 갱신한다.
  • 서비스 계정의 셸이 nologin→bash로 바뀌면 지속성 공격 신호다.
  • usermod·gpasswd 실행을 로그로 감시한다.

12. 다음 편 예고

다음 글 「37. userdel과 계정 삭제」 에서는 계정 삭제 시 남는 파일 소유권 문제 를 다룬다. 삭제된 계정의 파일이 UID 숫자로 남고, 같은 UID로 새 계정이 생기면 그 파일들을 물려받는 위험을 실제로 재현한다.


참고 자료


시리즈 이동

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

0개의 댓글