Cron Ran curl at Three in the Morning
Cron ran curl at three in the morning
한국어 원문으로 표시합니다.
이 실습은 VM 에서 돕니다
우분투 24.04 VM 한 대에 Falco 가 modern eBPF 드라이버로 이미 떠 있습니다. 시스콜 계측은 커널 기능이라 실습 파드에서는 아예 불가능합니다. 뜨는 데 2~3분 걸립니다(Falco 를 설치하기 때문입니다).
목표
제목의 사건을 잡는 규칙을 직접 씁니다. 목록과 매크로를 나누고, 알림을 JSON 파일로 남기고, 실제로 예약 작업을 심어 규칙이 잡는 것을 파일에서 확인합니다. 그다음 같은 규칙에 걸리는 정상 작업을 하나 더 만들어 그것만 예외로 빼고, 나쁜 것은 계속 잡히는지 다시 확인합니다.
왜 중요한가
로그 기반 탐지에는 구조적인 한계가 있습니다. 로그는 프로그램이 남기기로 한 것만 남습니다. 시스콜은 다릅니다 — 프로세스를 만들든 파일을 열든 커널을 거쳐야 하고, 커널을 속일 수는 없습니다.
그런데 시스콜을 다 보면 알림이 너무 많아집니다. 그래서 런타임 탐지의 실제 작업은 "무엇을 잡을까" 가 아니라 "무엇을 빼도 되는가" 입니다. 규칙 하나가 정상 백업 작업까지 잡으면 며칠 만에 아무도 알림을 안 봅니다. 그때 규칙을 넓게 고치면 진짜 사건도 함께 빠집니다. 예외를 좁게, 이유를 적어서 두는 습관이 탐지 체계의 수명을 정합니다.
단계
- Falco 의 판·드라이버·서비스 상태를
/root/falco/01-engine.txt에 저장하세요. /etc/falco/rules.d/labhub-cron.yaml에list하나,macro하나,rule하나로 규칙을 쓰세요. 출력에%user.name과%proc.cmdline이 들어가야 합니다./etc/falco/config.d/labhub-output.yaml에 JSON 출력과 파일 출력(/var/log/falco/events.json)을 켜고 서비스를 다시 시작하세요./etc/cron.d/telemetry를 만들어 매분 바깥으로 요청하게 하세요.- 1분 이상 기다렸다가 잡힌 알림 한 줄을
/root/falco/05-alert.json에 저장하세요. /etc/cron.d/backup-sync를 만들어 같은 규칙에 걸리는 정상 작업을 하나 더 두고, 그것만 규칙의exceptions로 뺀 뒤 서비스를 다시 시작하세요.events.json을 비운 뒤 예약 작업이 한 번 돌 때까지 기다려, 정상 작업은 안 잡히고 나쁜 것은 잡히는지/root/falco/07-verify.txt에 확인하세요.- 규칙의 근거를
/root/falco/08-report.md에## 무엇을 잡는가·## 왜 예외를 두었나·## auditd 와 무엇이 다른가·## 다음에 넓힐 곳네 절로 쓰세요.
참고
- 규칙 검증은
falco --validate /etc/falco/falco_rules.yaml --validate <내 파일>로 합니다. 기본 규칙 파일을 함께 주어야 합니다 —spawned_process같은 매크로가 그쪽에 정의돼 있습니다. - cron 이 셸을 띄우고 그 셸이 명령을 부르므로 부모는 셸입니다. 조상을 보려면
proc.aname[2]처럼 씁니다. - 서비스 이름은
falco지만 실제 유닛은 드라이버에 따라 다릅니다.systemctl show -p Id --value falco로 확인하고 저널은 그 이름으로 봅니다. - 예약 작업은 매분 돕니다. 기다리는 일은 단계로 나눠 두었으니 채점을 서두르지 마세요.
- 흔한 실수: 예외를
condition끝에and not …으로 녹여 버리는 것. 6개월 뒤에 아무도 그 조각의 이유를 모릅니다. - 흔한 실수: 예외를 너무 넓게 잡아 규칙 전체가 조용해지는 것. 7단계가 그것을 잡아 줍니다.
무엇이 어떤 드라이버로 도는가
falco --version 의 판 번호, 어떤 드라이버(유닛 이름)로 도는지, 서비스 상태를 /root/falco/01-engine.txt 에 저장하세요.
systemctl show -p Id --value falco 가 실제 유닛 이름을 알려 줍니다. falco 는 그 유닛의 별칭입니다. 드라이버를 모르면 '왜 안 잡히는지' 를 찾을 수 없습니다.
규칙 한 편을 쓴다
/etc/falco/rules.d/labhub-cron.yaml 에 list 하나·macro 하나·rule 하나를 쓰세요. 예약 작업 밑에서 외부 요청 도구가 실행된 것을 잡고, output 에 %user.name 과 %proc.cmdline 이 들어가야 하며 priority 는 WARNING 이상입니다.
list 와 macro 는 자기보다 앞에 정의된 것만 참조할 수 있어 목록 → 매크로 → 규칙 순으로 적습니다. cron 이 셸을 띄우므로 부모가 아니라 조상을 봐야 합니다. 다 쓰면 기본 규칙 파일과 함께 --validate 로 확인하세요.
알림을 파일에 남긴다
/etc/falco/config.d/labhub-output.yaml 에 json_output: true 와 파일 출력(/var/log/falco/events.json)을 켜고 서비스를 다시 시작하세요. falco.yaml 을 통째로 고치지 마세요.
config.d 아래의 파일은 기본 설정에 덧붙습니다. 다시 시작한 뒤 저널을 보면 어떤 설정 파일을 읽었는지 한 줄씩 찍힙니다 — 그것이 '진짜 반영됐다' 의 증거입니다.
사건을 심는다
/etc/cron.d/telemetry 를 만들어 매분 curl 로 바깥에 요청하게 하세요. /etc/cron.d 형식이므로 일정 다음에 실행할 사용자 칸이 있습니다.
매분은 * * * * * 입니다. 요청이 실제로 성공할 필요는 없습니다 — 프로세스가 실행됐다는 사실이 시스콜로 잡힙니다.
잡혔는지 파일에서 본다
예약 작업이 한 번 돌 때까지 기다렸다가, /var/log/falco/events.json 에서 내 규칙의 알림 한 줄을 골라 /root/falco/05-alert.json 에 저장하세요.
jq -c 'select(.rule == "<규칙 이름>")' /var/log/falco/events.json | tail -1 이면 한 줄이 나옵니다. 파일에는 Falco 내부 알림도 섞여 있으니 규칙 이름으로 거르세요.
정상 하나를 좁게 뺀다
/etc/cron.d/backup-sync 를 만들어 같은 규칙에 걸리는 정상 작업을 하나 더 두고, 그것만 규칙의 exceptions 로 뺀 뒤 서비스를 다시 시작하세요. condition 끝에 and not … 을 붙이지 마세요.
exceptions 는 name·fields·comps·values 로 씁니다. fields 에 볼 이벤트 필드를, comps 에 비교 방법을, values 에 값 묶음을 적으면 엔진이 조건 뒤에 and not (…) 으로 붙여 줍니다. 값을 넓게 잡으면 7단계에서 걸립니다.
둘 다 다시 돌려 본다
/var/log/falco/events.json 을 비운 뒤 예약 작업이 한 번 돌 때까지(최대 1분) 기다려, telemetry 는 잡히고 backup-sync 는 안 잡히는 것을 확인해 /root/falco/07-verify.txt 에 두 줄 이상으로 적으세요.
예외는 서비스가 규칙을 다시 읽어야 적용됩니다(앞 단계에서 다시 시작했습니다). 옛 알림이 남아 있으면 판단이 흐려지니 파일을 비우고 새로 받은 것만 보세요. 예외가 너무 넓으면 잡아야 할 것까지 조용해집니다.
규칙의 근거를 남긴다
/root/falco/08-report.md 에 ## 무엇을 잡는가·## 왜 예외를 두었나·## auditd 와 무엇이 다른가·## 다음에 넓힐 곳 네 절을 쓰세요. exceptions·priority·events.json 세 낱말이 본문에 나와야 합니다.
다음 사람이 이 규칙을 볼 때 가장 먼저 지우고 싶어지는 것이 예외입니다. 왜 두었는지가 적혀 있지 않으면 정말로 지웁니다. 앞 모듈의 커널 감사와 무엇이 겹치고 무엇이 다른지도 정리해 두세요.