시스템 보안 · 취약점 › B. 계정 · 인증 보안 강화 · 10/50편 (전체 060/450)
학습 단계: 2단계 · 설정 및 점검
실습 표기: 이 글의 명령어·출력·로그는 로컬 VMware 테스트 VM(Rocky Linux 9 / Ubuntu 22.04) 기준의 「실습 예시」이며, IP·계정·호스트명은 가상의 값입니다.
복잡도(059편)가 "비밀번호를 강하게"라면, 만료 정책은 "같은 비밀번호를 오래 쓰지 못하게"입니다. 설정은 /etc/shadow의 날짜 필드에 저장되고, chage로 조회·변경합니다.
chage -l devops 출력
Last password change : 2026-09-30 (shadow 3번 필드)
Password expires : 2026-12-29 (변경일 + MAX_DAYS)
Password inactive : 2027-01-12 (만료 + INACTIVE)
Account expires : never (shadow 8번 필드)
Minimum/Maximum/Warning : 1 / 90 / 7
지속성 목적의 약화
MAX_DAYS 99999 → 사실상 만료 없음(탈취한 비밀번호 영구 사용)
Account expires 제거 → 만료 예정이던 계정을 영구화
INACTIVE -1 → 만료 후에도 비활성화 안 됨
| 명령 | 용도 |
|---|---|
sudo chage -l 계정 | 계정별 만료 정책 조회 |
sudo chage -M 90 -m 1 -W 7 계정 | 최대/최소/경고일 설정 |
sudo chage -E 2026-12-31 계정 | 계정 만료일 설정 |
sudo awk -F: '{print $1,$3,$5,$8}' /etc/shadow | 변경일·MAX·만료일 일괄 |
sudo lastlog | 마지막 로그인(휴면 판단과 교차) |
# 1) 전 계정 만료 정책 요약 (사람 계정 위주)
sudo awk -F: '$3>=1000 && $1!="nobody"{print $1}' /etc/passwd | while read u; do
printf '%-12s ' "$u"; sudo chage -l "$u" | awk -F: '/Maximum|Account expires/{printf "%s:%s ", $1, $2}'; echo
done
# 2) 만료 없음(99999) 또는 만료일 미설정 계정 찾기
sudo awk -F: '$3>=1000 && ($5==99999 || $5=="") {print $1" MAX="$5}' /etc/shadow
# 3) 기준선 저장 (변경일·MAX·만료일만, 해시 제외)
sudo awk -F: '{print $1":"$3":"$5":"$8}' /etc/shadow | sort > /root/baseline/chage-$(date +%F).txt
diff /root/baseline/chage-2026-09-15.txt /root/baseline/chage-$(date +%F).txt
admin1 Maximum number of days between password change:90 Account expires:never
devops Maximum number of days between password change:90 Account expires:never
intern01 Maximum number of days between password change:90 Account expires:2026-11-30
$ sudo awk -F: '$3>=1000 && ($5==99999 || $5=="")' /etc/shadow
$
사람 계정은 MAX 90일, 임시 계정(intern01)은 만료일이 설정된 상태가 정상입니다.
$ diff chage-base.txt chage-now.txt
< intern01:20331:90:20422
> intern01:20331:99999:
< backup:20000:90:20300
> backup:20362:99999:
intern01: MAX 90→99999, 계정 만료일(20422) 제거 → 만료 예정이던 임시 계정이 영구화backup: 변경일이 최근(20362)으로 바뀌고 만료 해제 → 053편의 휴면 계정 재활성화와 같은 계정, 같은 흐름만료 정책 변경 로그입니다(가상의 예시 로그).
Oct 2 02:50:02 rocky9-web01 chage[12101]: changed password expiry for intern01
type=EXECVE msg=audit(1759341002.004:3901): argc=4 a0="chage" a1="-M" a2="99999" a3="intern01"
type=SYSCALL msg=audit(1759341002.004:3901): auid=1002 uid=0 comm="chage" exe="/usr/bin/chage" key="identity"
Oct 2 02:50:20 rocky9-web01 chage[12110]: changed password expiry for intern01
type=EXECVE msg=audit(1759341020.100:3905): argc=4 a0="chage" a1="-E" a2="-1" a3="intern01"
| 관찰 | 해석 |
|---|---|
chage -M 99999 | 비밀번호 만료 제거 |
chage -E -1 | 계정 만료일 제거(never) |
| 같은 계정 연속 변경 | 만료 관련 설정을 한 번에 해제 |
auid=1002 | 행위자 추적(devops) |
shadow를 직접 편집하면 chage 로그가 없으므로, FIM diff(날짜 필드 변화)로 보완합니다.
identity 키·FIM으로 감시하고, 변경일·MAX·만료일만 기준선으로 비교합니다(해시 제외).<group name="local,syssec_b,account,">
<rule id="101090" level="10">
<if_group>audit</if_group>
<match>a0="chage"</match>
<regex type="pcre2">a\d="(99999|-1|-E)"|a\d="never"</regex>
<description>비밀번호/계정 만료 해제(chage) — 지속성 목적 가능성</description>
</rule>
</group>
정규식은 chage 인자 배치에 따라 오탐·미탐이 생길 수 있으므로, -M 99999와 -E -1 각각을 wazuh-logtest로 검증한 뒤 조건을 분리하는 것이 안전합니다.
| 구분 | 핵심 내용 |
|---|---|
| 저장 위치 | /etc/shadow 날짜 필드, chage로 조회·변경 |
| 지속성 신호 | MAX 99999, Account expires 제거, INACTIVE -1 |
| 정상 운영 | 임시·퇴직 계정에 만료일 설정 |
| 탐지 | chage -M 99999 / -E -1, shadow 날짜 필드 FIM |
| 면접 포인트 | "만료 해제 = 탈취 계정을 오래 쓰려는 지속성 신호" |
다음 편 061. 계정 · 인증 보안 — 비밀번호 이력·재사용 제한(pam_pwhistory) 에서는 같은 비밀번호를 다시 쓰지 못하게 하는 비밀번호 이력·재사용 제한(pam_pwhistory)을 다룹니다.
이전 편: 059. 계정 · 인증 보안 — 비밀번호 정책 — pwquality 복잡도 설정
📚 시리즈 전체 보기: 시스템 보안 · 취약점