시스템 보안 · 취약점 › I. 지속성 · 재침투 징후 · 42/50편 (전체 442/450)
학습 단계: SOC 탐지 연계
실습 표기: 이 글의 명령어·출력·로그는 로컬 VMware 테스트 VM(Rocky Linux 9 / Ubuntu 22.04) 기준의 「실습 예시」이며, IP·계정·호스트명은 가상의 값입니다.
지속성 이벤트는 auditd, FIM, secure, cron, journal, 방화벽처럼 형식이 제각각인 로그에 흩어져 있습니다. 이를 같은 필드로 맞추는 정규화가 되어야 상관분석과 대시보드가 가능합니다.
지속성 이벤트 공통 스키마(예시)
@timestamp : UTC 시각
host.name : 호스트
actor : auid(원래 로그인 사용자) / euid
session : audit.ses
action : create / modify / enable / connect / listen
target.path : 지속성 위치 (/etc/cron.d/x)
persist.trigger : time / boot / login / event / exec / network
persist.class : account / auth / schedule / service / boot / shell / channel
method : 실행 파일(exe) · 명령(proctitle)
source : auditd / fim / secure / cron / fw
핵심: "trigger·class" 필드를 붙이면 I05 분류표가 그대로 검색 조건이 된다
감사 키를 persist_cron, persist_svc처럼 설계해 둔 이유가 여기서 드러납니다. 키 이름만으로 trigger·class를 매핑할 수 있기 때문입니다.
| 원본 | 매핑 근거 | 정규화 필드 |
|---|---|---|
| auditd | key·auid·exe·name | class·actor·method·target |
| Wazuh FIM | syscheck.path·event | action·target |
| secure | sshd·useradd 메시지 | action·actor |
| cron | CMD·REPLACE | trigger=time |
| 방화벽 | DST·DPT | class=channel |
# 감사 키 → 분류 매핑 표 (Logstash/Ingest 파이프라인 입력용, 분석 방법)
cat > /etc/logstash/persist_map.yml <<'Y'
"persist_cron": "schedule|time"
"persist_svc": "service|boot"
"persist_boot": "boot|boot"
"persist_shell": "shell|login"
"persist_preload": "boot|exec"
"persist_ssh": "auth|network"
"persist_pam": "auth|login"
"account_persist": "account|login"
"reentry_net": "channel|network"
"reentry_listen": "channel|network"
Y
# Logstash translate 필터 예: field => "[data][audit][key]" dictionary_path => ".../persist_map.yml"
# destination => "[persist][map]" 후 dissect로 class|trigger 분리
{"host.name":"web01","actor":"admin01","action":"create","target.path":"/etc/cron.d/backup",
"persist.class":"schedule","persist.trigger":"time","method":"/usr/bin/ansible-playbook","source":"auditd"}
모든 지속성 이벤트가 공통 필드를 갖고, actor가 원래 로그인 사용자(auid)로 채워지며 분류 필드가 비어 있지 않은 상태가 정상입니다.
{"host.name":"web01","actor":"unset","persist.class":null,"source":"auditd",
"data.audit.key":"persist_udev"}
→ auid 미설정(4294967295), 매핑표에 없는 키
정규화 품질 점검 흐름입니다(가상의 예시).
[수집] Wazuh agent → manager → Filebeat → Elasticsearch
↓
[정규화] 키 매핑 · auid→actor · 시각 UTC
↓
[품질 점검] class·trigger·actor 누락 비율
↓
[보정] 매핑표·디코더 보강 → 재처리
| 품질 지표 | 목표 |
|---|---|
| class 누락률 | 0% |
| actor=unset 비율 | 설명 가능한 수준 |
| 수집 지연 | 수 분 이내 |
auid가 unset인 지속성 이벤트는 부팅·데몬 동작일 수도 있지만, 웹셸처럼 로그인 없이 실행된 공격일 수도 있습니다. 이 경우 ppid·uid로 보완해 actor를 채웁니다.
<!-- 실습 예시 룰: 적용 전 wazuh-logtest 및 테스트 환경 검증 필요 -->
<group name="local,syssec_i,persistence,">
<rule id="108410" level="6">
<if_sid>108000</if_sid>
<field name="audit.key" type="pcre2">^(persist_|account_persist|reentry_)</field>
<field name="audit.auid" type="pcre2">^(4294967295|unset)$</field>
<description>로그인 사용자(auid) 미설정 상태의 지속성 이벤트(actor 보완 필요)</description>
<mitre><id>TA0003</id></mitre>
</rule>
</group>
정규화 품질을 위한 보조 룰입니다. auid가 없는 지속성 이벤트를 별도로 표시해 웹셸·데몬 경유 행위인지 추가 확인하도록 합니다.
| 필드 | 역할 |
|---|---|
| actor·session | 원래 사용자·세션 |
| class·trigger | I05 분류 검색 |
| target·method | 위치·도구 |
| 품질 | 누락률 관리 |
| 면접 포인트 | "흩어진 로그를 같은 필드로 — 감사 키 설계가 정규화를 쉽게 만든다" |
다음 편 443. 지속성·재침투 — 지속성·재침투 이벤트 상관분석 에서는 정규화된 지속성·재침투 이벤트를 세션·주체·실행 대상·호스트 기준으로 상관해 단일 이벤트로는 약한 신호를 공격 체인으로 확정하는 방법을 다룹니다.
이전 편: 441. 지속성·재침투 — 지속성·재침투 타임라인 작성
📚 시리즈 전체 보기: 시스템 보안 · 취약점