시스템 보안 · 취약점 › I. 지속성 · 재침투 징후 · 22/50편 (전체 422/450)
학습 단계: 스케줄·서비스·부팅 지속성 탐지
실습 표기: 이 글의 명령어·출력·로그는 로컬 VMware 테스트 VM(Rocky Linux 9 / Ubuntu 22.04) 기준의 「실습 예시」이며, IP·계정·호스트명은 가상의 값입니다.
systemd timer는 cron의 현대적 대체 수단입니다(T1053.006). .timer 유닛이 정한 주기에 맞춰 같은 이름의 .service를 실행합니다. cron만 점검하는 조직에서는 timer가 사각지대가 됩니다.
timer 지속성 구조
update-check.timer [Timer] OnBootSec=5min OnUnitActiveSec=15min
↓ 주기마다 실행
update-check.service [Service] ExecStart=/var/tmp/.u/run.sh
활성화: systemctl enable --now update-check.timer
사용자 timer: ~/.config/systemd/user/*.timer (root 불필요)
핵심: timer는 cron 로그에 남지 않는다 — list-timers와 journal로 본다
timer와 service는 쌍으로 동작하므로, 의심 timer를 발견하면 짝이 되는 service의 ExecStart까지 반드시 확인합니다.
| 확인 | 명령 | 포인트 |
|---|---|---|
| 전체 timer | systemctl list-timers --all | 신규 timer |
| 사용자 timer | systemctl --user -M <user>@ list-timers | 사용자 수준 |
| 쌍 확인 | systemctl cat <name>.timer <name>.service | ExecStart |
| 실행 기록 | journalctl -u <name>.service | 주기 실행 |
# systemd timer 점검 (분석 방법)
systemctl list-timers --all --no-legend | awk '{print $(NF-1)}' | sort
for t in $(systemctl list-timers --all --no-legend | awk '{print $(NF-1)}'); do
s=$(systemctl show -p Unit --value "$t")
f=$(systemctl show -p FragmentPath --value "$s")
rpm -qf "$f" >/dev/null 2>&1 || dpkg -S "$f" >/dev/null 2>&1 || echo "미소유: $t → $s ($f)"
done
sudo find /home /root -path '*systemd/user/*.timer' 2>/dev/null
dnf-makecache.timer → dnf-makecache.service (dnf 소유)
logrotate.timer → logrotate.service (logrotate 소유)
미소유 timer: 없음
모든 timer와 짝 service가 패키지에 속하거나 승인된 배포이고, 사용자 timer가 없는 상태가 정상입니다.
미소유: update-check.timer → update-check.service (/etc/systemd/system/update-check.service)
ExecStart=/var/tmp/.u/run.sh
journalctl: Started update-check.service (15분 간격 반복)
timer 지속성 분석 흐름입니다(가상의 예시).
[timer 목록] list-timers --all (시스템 + 사용자)
↓
[쌍 해석] timer → Unit= → service ExecStart
↓
[소유·경로] 패키지 소유 · 실행 파일 위치
↓
[실행 기록] journalctl -u (최초 실행 = 설치 시점 추정)
| 항목 | 확인 |
|---|---|
| OnBootSec | 부팅 후 실행 |
| OnUnitActiveSec | 주기 |
| Persistent | 놓친 실행 보충 |
Persistent=true가 있으면 서버가 꺼져 있던 동안 놓친 실행을 부팅 직후 보충하므로, 재부팅 직후 실행 기록도 확인해야 합니다.
<!-- 실습 예시 룰: 적용 전 wazuh-logtest 및 테스트 환경 검증 필요 -->
<group name="local,syssec_i,persistence,">
<rule id="108210" level="12">
<if_sid>108000</if_sid>
<field name="audit.key">persist_svc</field>
<field name="audit.file.name" type="pcre2">systemd/(system|user)/.*\.timer$</field>
<description>systemd timer 유닛 생성·수정(주기 실행 지속성 의심)</description>
<mitre><id>T1053.006</id></mitre>
</rule>
</group>
.timer 파일 생성은 패키지 설치 외에는 드물어 독립 룰로 경보합니다. 사용자 디렉터리(~/.config/systemd/user)도 감시 경로에 넣어야 탐지됩니다.
systemctl disable --now <timer> 후 timer·service·스크립트를 격리합니다.| 항목 | 확인 |
|---|---|
| 목록 | list-timers --all |
| 쌍 | timer → service |
| 사용자 | ~/.config/systemd/user |
| 기록 | journalctl -u |
| 면접 포인트 | "timer는 cron 로그에 안 남는 cron — timer와 service를 쌍으로 본다" |
다음 편 423. 지속성·재침투 — systemd drop-in·generator 악용 탐지 에서는 정상 서비스에 drop-in override로 ExecStartPre를 끼워 넣거나 generator로 유닛을 동적 생성하는 은밀한 systemd 지속성을 탐지하는 방법을 다룹니다.
이전 편: 421. 지속성·재침투 — systemd 서비스 지속성 탐지
📚 시리즈 전체 보기: 시스템 보안 · 취약점