LabHub
배우기 러닝패스 코스

Cron Ran curl at Three in the Morning

Reconstruct one hour of that night

LabHub 에서 이어서 보기

한국어 원문으로 표시합니다.

목표

한 사건의 자료 네 종류를 받아 조사를 한 바퀴 돕니다. 세고, 집고, 보존하고, 타임라인으로 엮고, 축을 잡아 클러스터까지 따라가고, 조치 순서를 정하고, 사후 분석 보고서를 씁니다.

왜 중요한가

알림이 울린 뒤 30분 동안 무엇을 하느냐가 그 사건의 결말을 정합니다. 급한 마음에 파드를 지우고 노드를 재부팅하면 침입 경로가 함께 사라지고, 반대로 증거를 완벽하게 모으는 동안 유출된 자격증명으로 다른 네임스페이스가 털립니다.

그래서 대응은 "무엇이 옳은가" 가 아니라 "무엇을 먼저 하는가" 의 문제이고, 그 순서는 사건이 나기 전에 정해 두어야 합니다. 휘발성이 큰 것부터 모으고, 원본은 건드리지 않고, 시각은 UTC 로 통일하고, 자격증명 폐기는 미루지 않는다 — 이런 규칙들은 전부 누군가 한 번씩 잃어 보고 나서 생겼습니다.

이 실습의 자료는 합성한 것입니다. 대신 형식은 실제와 같습니다. Falco 의 JSON 출력, 커널 감사의 원본 레코드, journalctl -o json 의 필드, 쿠버네티스 감사 이벤트를 그대로 씁니다.

단계

  1. 자료 네 종의 줄 수를 세어 /root/ir/01-sources.tsv 에 저장하세요.
  2. 가장 이른 Falco 알림의 규칙 이름·시각·PID 를 /root/ir/02-first.json 에 저장하세요.
  3. 자료 네 종을 /root/ir/evidence/ 로 복사하고 manifest.sha256 을 남기세요.
  4. 네 출처를 하나의 시간축에 올린 타임라인을 /root/ir/04-timeline.tsv 에 8행 이상 쓰세요.
  5. 축 네 개(pid·cron-file·c2-host·k8s-identity)를 /root/ir/05-pivot.tsv 에 값과 근거로 적으세요.
  6. 조치 여섯 가지의 시점과 근거를 /root/ir/06-containment.tsv 에 적으세요.
  7. 훔친 신원이 클러스터에서 한 일을 /root/ir/07-k8s.tsv 에 적으세요.
  8. 사후 분석 보고서를 /root/ir/08-postmortem.md 에 쓰세요.

참고

무엇이 있는지 센다

/opt/lab/fixtures/detection/incident/falco.jsonl·audit.log·cron.jsonl·kube-audit.jsonl 네 파일의 줄 수를 세어 /root/ir/01-sources.tsv 에 한 줄씩 파일이름<탭>줄수 로 저장하세요.

wc -l 이면 됩니다. 조사에서 이 단계를 건너뛰면 나중에 '그 로그도 있었네' 가 나옵니다.

최초 알림을 집는다

falco.jsonl 에서 가장 이른 알림을 찾아 규칙 이름·시각·PID 를 /root/ir/02-first.json{"rule": …, "time": …, "pid": …} 로 저장하세요.

jq -s 'min_by(.time)' 로 가장 이른 것을 고를 수 있습니다. PID 는 output_fields 안에 있습니다. 시각은 파일에 적힌 값을 그대로 씁니다.

원본을 건드리지 않고 보존한다

자료 네 종을 /root/ir/evidence/ 로 복사하고, 그 디렉터리에서 sha256sum -c 로 검증되는 /root/ir/evidence/manifest.sha256 을 만드세요.

sha256sum <파일들> > manifest.sha256 은 상대 경로로 적습니다. 검증은 그 디렉터리 안에서 sha256sum -c manifest.sha256 으로 합니다.

하나의 시간축에 올린다

네 출처의 기록을 /root/ir/04-timeline.tsv 에 8행 이상, 시각<탭>출처<탭>행위자<탭>무슨 일 네 칸으로 시간 오름차순으로 쓰세요. 네 출처가 모두 한 번 이상 나와야 합니다.

출처 이름은 falco·auditd·cron·kube-audit 로 통일합니다. 커널 감사 원본의 에폭 초는 date -u -d @<초> +%Y-%m-%dT%H:%M:%SZ 로 바꿉니다. journald 의 __REALTIME_TIMESTAMP 는 마이크로초입니다.

축을 잡고 건너뛴다

/root/ir/05-pivot.tsv 에 네 줄을 축<탭>값<탭>근거 로 쓰세요. 축 이름은 pid·cron-file·c2-host·k8s-identity 이고, 근거에는 어느 파일의 무엇을 보고 그렇게 판단했는지를 10자 이상 적습니다.

pid 는 임시 디렉터리에서 실행된 프로세스의 것입니다. cron-file 은 그날 밤 새로 생긴 예약 작업이고 커널 감사 원본의 PATH 레코드에 있습니다. k8s-identity 는 감사 로그의 user.username 입니다.

무엇을 먼저 하는가

조치 여섯 가지를 /root/ir/06-containment.tsv조치<탭>시점<탭>근거 로 적으세요. 시점은 지금·나중·안함 중 하나이고 근거는 20자 이상입니다.

휘발성이 큰 것부터 모읍니다. 그리고 노드를 꺼도 유효한 것이 하나 있습니다 — 그것은 미룰 수 없습니다.

훔친 신원이 클러스터에서 한 일

kube-audit.jsonl 에서 system:node:edge-07 이 한 요청을 전부 찾아 /root/ir/07-k8s.tsvverb<탭>리소스<탭>네임스페이스<탭>이름<탭>응답코드 다섯 칸으로 쓰세요. 네임스페이스나 이름이 없으면 - 로 적습니다.

jq -r 'select(.user.username == …)' 로 걸러 냅니다. 거부된 요청(403)도 행위입니다 — 무엇을 시도했는지가 의도를 말해 줍니다.

다음 주를 바꾸는 글

/root/ir/08-postmortem.md## 요약·## 타임라인·## 영향·## 원인·## 탐지 공백·## 재발 방지 여섯 절을 쓰세요. 본문에는 명령제어 주소, 자격증명이 쓰인 네임스페이스, 붙잡힌 지속화 수단의 경로가 나와야 합니다.

## 탐지 공백 이 이 보고서에서 가장 중요한 절입니다. 규칙이 없었는지, 알림이 아무도 안 보는 곳으로 갔는지, 로그 자체가 없었는지는 전혀 다른 처방으로 이어집니다. 사람 이름으로 끝나는 보고서는 다음 주에 같은 사고를 부릅니다.