파일 · 권한 · 사용자 관리 48 / 50 · Part 5. 권한 상승과 Linux 보안
실습 환경: Rocky Linux 9.8 · Ubuntu 24.04.5 (Docker 격리 컨테이너, 테스트 계정analyst)
기초편 연계: 「리눅스 시스템 기초」 18. Linux 사용자와 그룹 · 30. Linux 명령어를 활용한 보안 점검
47편이 파일(SUID) 측면의 점검이었다면, 이번 글은 계정 측면의 종합 점검 이다. Part 4에서 배운 계정 지식을 하나의 점검 체크리스트로 묶는다.
점검 항목:
이 중 UID 0 중복 이 최우선이다. 이름이 무엇이든 UID가 0이면 root이기 때문이다(31편). 이번 글에서는 백도어 계정·무암호 계정·시스템 계정 셸을 심어 둔 테스트 환경에서 이들을 모두 찾아낸다.
| 항목 | 명령 | 정상 |
|---|---|---|
| UID 0 계정 | awk -F: '$3==0' /etc/passwd | root 뿐 |
| 무암호 계정 | awk -F: '$2==""' /etc/shadow | 없음 |
| 시스템 계정 셸 | awk -F: '$3<1000 && $7~/sh$/' | sync 류 외 없음 |
| 중복 UID | cut -d: -f3 /etc/passwd \| sort \| uniq -d | 없음 |
| sudo 권한 | getent group wheel, ls /etc/sudoers.d/ | 최소 |
| 우선순위 | 발견 | 대응 |
|---|---|---|
| 1 | UID 0 추가 계정 | 즉시 격리·조사 |
| 2 | 무암호 계정 | 즉시 잠금 |
| 3 | 시스템 계정 로그인 셸 | nologin으로 변경 |
| 4 | 과도한 sudo | 규칙 축소 |
useradd -o -u로 같은 UID의 계정을 만들 수 있다. 특히 UID 0의 중복 은 백도어 root의 전형적 형태다. 커널은 UID로 판단하므로 이름이 달라도 동등한 root다.

계정 점검은 /etc/passwd와 /etc/shadow를 awk로 분석하는 것이 핵심이다. 각 점검은 특정 필드의 이상값을 찾는다.
이 점검들을 스크립트로 묶어 cron으로 정기 실행 하고, 결과를 기준값과 비교해 변화만 알리면 효과적인 계정 모니터링이 된다. SIEM에 연동하면 계정 이상을 실시간에 가깝게 탐지할 수 있다.
useradd -o -u 0처럼 중복 UID 0을 허용하는 옵션이 존재한다는 점을 아는 것도 중요하다. 공격자는 이 옵션으로 백도어 root를 만든다.
테스트 환경에
backdoor(UID 0 중복),nopw(무암호),svc-fake(시스템명이지만 셸 보유)를 심어 뒀다. root 권한 실습이다.
# ① UID 0 계정 (root 외 = 백도어)
awk -F: '$3==0 {print $1}' /etc/passwd
# ② 빈 비밀번호 계정
awk -F: '($2=="") {print "무암호: "$1}' /etc/shadow
# ③ 로그인 셸을 가진 계정
awk -F: '$7 ~ /(bash|sh)$/ {print $1" (uid="$3", "$7")"}' /etc/passwd
# ④ 시스템 계정(UID<1000)에 유효 셸?
awk -F: '$3<1000 && $7 ~ /(bash|sh)$/ {print "시스템계정 셸: "$1}' /etc/passwd
# ⑤ 중복 UID
awk -F: '{print $3}' /etc/passwd | sort | uniq -d | while read u; do
echo "중복 UID $u: $(awk -F: -v u=$u '$3==u{print $1}' /etc/passwd | tr '\n' ' ')"
done
# ⑥ sudo 권한
getent group wheel
ls /etc/sudoers.d/

텍스트 원본(실제 출력):
[root@rocky9-lab ~]# echo "=== ① UID 0 계정 (root 외 = 백도어) ==="
=== ① UID 0 계정 (root 외 = 백도어) ===
[root@rocky9-lab ~]# awk -F: '$3==0 {print $1}' /etc/passwd
root
backdoor
[root@rocky9-lab ~]# echo "=== ② 빈 비밀번호 계정 ==="
=== ② 빈 비밀번호 계정 ===
[root@rocky9-lab ~]# awk -F: '($2=="") {print "무암호: "$1}' /etc/shadow
무암호: nopw
[root@rocky9-lab ~]# echo "=== ③ 로그인 셸을 가진 계정 목록 ==="
=== ③ 로그인 셸을 가진 계정 목록 ===
[root@rocky9-lab ~]# awk -F: '$7 ~ /(bash|sh)$/ {print $1" (uid="$3", "$7")"}' /etc/passwd
root (uid=0, /bin/bash)
analyst (uid=1000, /bin/bash)
backdoor (uid=0, /bin/bash)
nopw (uid=1001, /bin/bash)
svc-fake (uid=1002, /bin/bash)
[root@rocky9-lab ~]# echo "=== ④ 잠기지 않은 계정 중 UID<1000 (시스템 계정에 유효 셸?) ==="
=== ④ 잠기지 않은 계정 중 UID<1000 (시스템 계정에 유효 셸?) ===
[root@rocky9-lab ~]# awk -F: '$3<1000 && $7 ~ /(bash|sh)$/ {print "시스템계정 셸: "$1}' /etc/passwd
시스템계정 셸: root
시스템계정 셸: backdoor
[root@rocky9-lab ~]# echo "=== ⑤ 중복 UID 탐지 ==="
=== ⑤ 중복 UID 탐지 ===
[root@rocky9-lab ~]# awk -F: '{print $3}' /etc/passwd | sort | uniq -d | while read u; do echo "중복 UID $u: $(awk -F: -v u=$u '$3==u{print $1}' /etc/passwd | tr '\n' ' ')"; done
중복 UID 0: root backdoor
[root@rocky9-lab ~]# echo "=== ⑥ sudo 권한 계정 ==="
=== ⑥ sudo 권한 계정 ===
[root@rocky9-lab ~]# getent group wheel
wheel:x:10:
[root@rocky9-lab ~]# ls /etc/sudoers.d/ 2>/dev/null
| 출력 | 해석 |
|---|---|
awk '$3==0' → root, backdoor | UID 0이 둘 → backdoor는 백도어 root |
무암호: nopw | nopw 계정은 비밀번호 없이 로그인 가능 |
로그인 셸 목록에 backdoor, nopw, svc-fake | 모두 대화형 셸 보유 |
시스템계정 셸: root, backdoor | backdoor가 UID 0(시스템 대역)이면서 셸 보유 |
중복 UID 0: root backdoor | 중복 UID 탐지가 backdoor를 정확히 지목 |
wheel:x:10: | wheel 그룹 구성원 없음(이 환경) |
중복 UID 0: root backdoor가 최우선 IOC다. backdoor는 이름만 다를 뿐 root와 동일한 권한을 가진 백도어 계정이다. 즉시 격리·조사·삭제 대상이다.
nopw(무암호)도 위험하다. 비밀번호 없이 로그인되므로 즉시 잠가야 한다.
| 발견 | 위험 | 대응 |
|---|---|---|
| UID 0 추가 계정 | 백도어 root | passwd -l → 조사 → 삭제 |
| 무암호 계정 | 무인증 로그인 | 즉시 passwd -l |
| 시스템 계정 셸 | 발판 제공 | usermod -s nologin |
| 중복 UID | 소유권 혼란·은닉 | 조사 후 정리 |
| 과도한 sudo | 권한 상승 | 규칙 축소(42편) |
대응 순서: UID 0 추가 계정과 무암호 계정은 발견 즉시 잠금 이 원칙이다. 조사보다 차단이 먼저다(추가 피해 방지). 잠근 뒤 생성 경위를 로그로 조사한다(49편).
[정기 점검] 계정 점검 스크립트를 cron 으로 실행
awk -F: '$3==0{print "UID0:",$1}' /etc/passwd
awk -F: '$2==""{print "무암호:",$1}' /etc/shadow
awk -F: '$3<1000 && $7~/sh$/{print "시스템셸:",$1}' /etc/passwd
awk -F: '{print $3}' /etc/passwd | sort | uniq -d
↓
[비교] 결과를 Baseline 과 diff → 변화만 알림 (31편)
↓
[Detection] /etc/passwd·shadow 변경, UID 0 추가를 FIM·auditd 로 실시간
↓
[Evidence] 변경 시각(ctime), 계정 생성 로그(useradd), 로그인 이력(last)
↓
[Response] 즉시 잠금 → 조사 → 삭제(37편 안전 절차)
| 관점 | 내용 |
|---|---|
| 자동화 | 점검 스크립트 + cron + SIEM 연동 |
| 최우선 IOC | UID 0 추가·중복, 무암호 계정 |
| Baseline | 정상 계정·그룹 목록과 비교해 변화 탐지 |
| 실수 | 결과 | 예방 |
|---|---|---|
| UID 0 중복 미점검 | 백도어 방치 | 정기 점검 최우선 |
| 조사부터 하고 차단 지연 | 추가 피해 | 즉시 잠금 우선 |
| 무암호 계정 방치 | 무인증 접근 | 즉시 잠금 |
| 점검을 수동으로만 | 누락·지연 | 스크립트+cron |
| Baseline 없이 점검 | 변화 판단 곤란 | 기준값 관리 |
[ ] UID 0 계정이 root 뿐인지 점검했다
[ ] 무암호 계정을 탐색했다
[ ] 시스템 계정의 로그인 셸을 점검했다
[ ] 중복 UID 를 탐지했다
[ ] sudo 권한 보유자를 확인했다
[ ] 발견 시 즉시 잠금이 우선임을 이해했다
다음 글 「49. Linux 권한 변경 로그 분석」 에서는 이번 글에서 찾은 이상 계정이 언제·누구에 의해 만들어졌는지 로그로 추적한다. sudo·useradd·usermod·passwd의 로그 형식과, chmod처럼 기본 로그에 남지 않는 행위를 auditd로 잡는 방법을 다룬다.