Linux 시스템 보안 기초 · 07/50편

이 글은 리눅스 시스템 기초 · 파일 · 권한 · 사용자 관리 · 서비스 · 프로세스 관리 시리즈를 선행 학습으로 두고, 동일한 개념을 보안관제(SOC) 관점에서 한 단계 확장합니다.

선행 학습

1. 들어가며

/etc/passwd가 명부라면 /etc/shadow는 금고입니다. 비밀번호 해시와 만료 정책이 여기 있습니다. 이 파일 하나가 뚫리면 오프라인 크래킹으로 모든 계정이 위험해집니다. 이번 편은 해시 필드 해석과 계정 잠금 상태 판별에 집중합니다.

2. 핵심 개념

shadow 한 줄의 구조입니다.

user : $id$salt$hash : lastchg : min : max : warn : inactive : expire :

2번 필드(해시)의 $id$ 접두사가 알고리즘을 나타냅니다.

id알고리즘보안성
11MD5취약(사용 금지)
55SHA-256보통
66SHA-512권장(전통적 기본)
yyyescrypt최신 권장(현대 배포판 기본)
$6$ AbCdEf.. $ Hj9x....(hash)
 │     │           │
 │     │           └ 해시값
 │     └ salt (레인보우 테이블 방어)
 └ 알고리즘 ID ($1 MD5 / $5 SHA256 / $6 SHA512 / $y yescrypt)

3. 동작 원리

로그인 시 입력한 비밀번호에 저장된 salt를 붙여 동일 알고리즘으로 해시한 뒤, shadow의 해시와 비교합니다. salt가 있어 같은 비밀번호라도 계정마다 해시가 달라지고, 이것이 레인보우 테이블 공격을 무력화합니다.

2번 필드가 *나 !이면 해당 계정으로 비밀번호 로그인 불가(잠김/비활성)를 뜻합니다. !로 시작하면 잠긴 상태입니다. 반대로 필드가 비어 있으면 비밀번호 없이 로그인 가능해 매우 위험합니다.

4. 명령어 실습

# 사용 중인 해시 알고리즘 분포 (약한 MD5가 있나?)
sudo awk -F: '$2 ~ /^\$/ {split($2,a,"$"); print a[2]}' /etc/shadow | sort | uniq -c

# 비밀번호가 비어 있는 계정 (즉시 조치 대상)
sudo awk -F: '$2=="" {print $1" (EMPTY PASSWORD)"}' /etc/shadow

# 잠기지 않은(로그인 가능) 계정만
sudo awk -F: '$2 !~ /^[*!]/ && $2!="" {print $1}' /etc/shadow

5. 실행 결과

실습 환경(alice/bob 생성) 실제 실행 결과입니다. (실제 캡처)

$ sudo awk -F: '$2 ~ /^\$/ {split($2,a,"$"); print a[2]}' /etc/shadow | sort | uniq -c
      2 y

$ sudo awk -F: '$2=="" {print $1" (EMPTY PASSWORD)"}' /etc/shadow
(출력 없음)

해시가 모두 y(yescrypt)이고 빈 비밀번호 계정이 없으므로 정상입니다. 만약 $1$(MD5)이 나오면 약한 해시, 빈 필드가 나오면 즉시 잠가야 합니다.

6. 보안 관점 — 정상 사용 vs 악용

  • 정상: 강한 해시(6/6/y), 서비스 계정은 !/*로 잠김, 빈 비밀번호 없음.
  • 악용/위험 징후:
    • MD5(11) 같은 약한 해시 → 오프라인 크래킹 용이
    • 빈 비밀번호 필드 → 인증 없이 로그인
    • 원래 잠겨 있던 계정이 활성화됨 → 백도어

shadow 파일 자체 유출이 최악의 시나리오이므로, 권한(0640, group shadow)과 접근 감사가 핵심입니다.

7. 탐지 방법

  • 약한 해시/빈 비밀번호 정기 스캔(위 awk)
  • shadow 읽기 감사: auditd -w /etc/shadow -p r -k shadow_read — 읽기 시도 자체가 이상
  • 권한 점검: stat -c '%a %U %G' /etc/shadow 가 640 root shadow인지

8. SOC 관점 — SIEM · Wazuh · IOC

shadow 읽기(read) 이벤트는 정상 운영에서 거의 발생하지 않으므로 고신뢰 IOC입니다. auditd로 read watch를 걸면, 웹서버 같은 비관리 프로세스가 shadow를 읽는 순간을 잡을 수 있습니다. 아래는 이 시리즈 실습에서 실제로 cat /etc/shadow를 auditd가 포착한 로그입니다. (실제 캡처)

type=SYSCALL ... syscall=openat success=yes ... comm=cat exe=/usr/bin/cat key=shadow_watch
type=PATH ... name=/etc/shadow inode=... mode=file,640 ouid=root ogid=shadow

9. 실습 체크리스트

[ ] 해시 알고리즘 분포 확인(약한 해시 여부)
[ ] 빈 비밀번호 계정 점검
[ ] shadow 권한(640 root shadow) 확인
[ ] shadow read watch 설정

10. 핵심 정리

  • idid 접두사로 해시 알고리즘을 판별한다(6/6/y 권장, $1 위험).
  • salt는 레인보우 테이블 공격을 무력화한다.
  • *, ! 는 잠긴 계정, 빈 필드는 비밀번호 없는 위험 계정이다.
  • shadow 읽기 시도는 거의 발생하지 않는 고신뢰 IOC다.
  • 권한 0640(group shadow)과 read 감사가 핵심 방어다.

11. 다음 편

다음 편에서는 08. Linux Password 정책 를 다룹니다. 해시를 안전하게 유지하는 것과 별개로, 비밀번호 정책(만료·복잡도·잠금)을 어떻게 설정·점검하는지 봅니다.


본 실습은 격리된 테스트 VM(Rocky Linux / Ubuntu, VMware) 및 테스트 계정 환경을 기준으로 하며, 운영 서버를 대상으로 하지 않습니다. 실행 결과는 실제 캡처와 예시 출력을 명확히 구분해 표기합니다.

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

0개의 댓글