LabHub
배우기 러닝패스 코스

Cron Ran curl at Three in the Morning

Rewrite one rule six times

LabHub 에서 이어서 보기

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

목표

합성한 프로세스 실행 기록 24건을 놓고 Sigma 규칙을 여섯 편 씁니다. 매번 실제로 돌려 몇 건을 맞히고 몇 건을 놓쳤는지 숫자로 확인하면서 규칙을 좁혀 갑니다.

왜 중요한가

탐지 규칙이 현장에서 죽는 이유는 대개 문법이 아닙니다. 너무 넓어서 오탐이 쌓이면 사람들이 알림을 안 보게 되고, 너무 좁아서 주소 하나가 바뀌면 아무것도 못 잡습니다. 둘 사이를 찾는 유일한 방법은 자료에 돌려 보는 것입니다. 규칙을 쓰고 눈으로 읽어 "맞겠지" 하고 배포하는 습관이 탐지 공백의 가장 큰 원인입니다.

그래서 이 실습은 규칙을 쓸 때마다 사건 기록에 적용해 봅니다. 맞은 건과 잘못 잡은 건이 숫자로 나오면, "이 조건을 넣으면 무엇이 함께 들어오는가" 를 감이 아니라 관찰로 알게 됩니다. 이것이 탐지 엔지니어링이 보안 업무 중에서도 유난히 소프트웨어 공학을 닮은 이유입니다 — 규칙은 코드이고, 사건 기록은 시험 자료입니다.

단계

  1. 사건 기록을 부모 프로세스별로 세어 /root/sigma/01-parents.txt 에 저장하세요.
  2. cron 이 부모인 실행을 전부 잡는 최소 규칙을 /root/sigma/02-cron-any.yml 에 쓰세요.
  3. 그중 명령줄에 curl 이나 wget 이 있는 것만 잡도록 좁혀 /root/sigma/03-outbound.yml 에 쓰세요. selection 은 하나만 씁니다.
  4. 사내 저장소(repo.corp.internal)로 보내는 정상 백업을 필터로 덜어 내 /root/sigma/04-filtered.yml 에 쓰세요. conditionnot 을 씁니다.
  5. 주소를 쓰지 말고 행위로 잡는 규칙을 /root/sigma/05-behaviour.yml 에 쓰세요. 받아 온 것을 셸에 파이프로 넘기는 것과 셸을 붙여 바깥으로 연결하는 것, 두 가지입니다. |re 수식어를 반드시 씁니다.
  6. 예약 작업의 외부 요청과 역방향 셸을 selection_ 으로 시작하는 두 선택으로 나누고 1 of selection_* 로 묶어 /root/sigma/06-combined.yml 에 쓰세요. 사내 저장소 필터는 공통으로 겁니다.
  7. 6번 규칙에 배포용 메타데이터를 채워 /root/sigma/07-release.yml 에 쓰세요.
  8. 3번과 7번 규칙의 판정 결과를 /root/sigma/08-review.md 에 숫자와 판단으로 적으세요.

참고

자료부터 훑는다

/opt/lab/fixtures/detection/proc_events.jsonl 을 부모 프로세스(ParentImage)별로 세어 /root/sigma/01-parents.txt 에 저장하세요. 한 줄에 경로 하나와 그 건수가 함께 있으면 됩니다.

jq -r '.ParentImage' 로 값만 뽑은 뒤 sort | uniq -c 로 셉니다. 규칙을 쓰기 전에 무엇이 얼마나 있는지 보는 습관을 들이는 단계입니다.

가장 작은 규칙

cron 이 부모인 실행을 전부 잡는 최소 Sigma 규칙을 /root/sigma/02-cron-any.yml 에 쓰세요. 필수 항목(title·logsource·detection)만 있으면 됩니다.

detection 아래에 이름 붙인 선택 하나를 두고 condition 에 그 이름을 적습니다. 사건의 ParentImage 값이 무엇인지는 1단계 결과에 있습니다.

바깥으로 나간 것만

2번 규칙을 좁혀 명령줄에 curl 이나 wget 이 있는 것만 잡게 /root/sigma/03-outbound.yml 에 쓰세요. detection 의 선택은 하나만 둡니다.

한 선택 안에서 필드를 두 개 적으면 AND 이고, 한 필드에 값을 리스트로 주면 OR 입니다. 부분 문자열을 보려면 필드 이름 뒤에 수식어를 붙입니다.

정상 하나를 덜어 낸다

3번 결과에서 사내 저장소(repo.corp.internal)로 보내는 정상 백업을 빼고 /root/sigma/04-filtered.yml 에 쓰세요. 선택을 좁히지 말고 필터를 따로 두어 conditionnot 으로 붙입니다.

detection 아래에 선택을 두 개 두고 이름을 다르게 붙입니다. conditionselection and not <필터이름> 꼴이 됩니다.

주소가 아니라 행위로

받아 온 것을 셸에 파이프로 넘기는 것과, 셸을 붙여 바깥으로 연결하는 것 두 가지를 잡는 규칙을 /root/sigma/05-behaviour.yml 에 쓰세요. |re 수식어를 쓰고, 규칙 안에 목적지 주소를 적지 마세요.

정규식 수식어는 필드|re: '<정규식>' 꼴입니다. 파이프 문자와 -e /bin/sh 같은 조각이 무엇을 뜻하는지 1단계에서 본 명령줄을 다시 읽어 보세요. 두 갈래는 선택 두 개로 나누고 1 of 로 묶어도 됩니다.

두 갈래를 하나로

예약 작업의 외부 요청과 역방향 셸을 selection_ 으로 시작하는 선택 두 개로 나누고 1 of selection_* 로 묶어 /root/sigma/06-combined.yml 에 쓰세요. 사내 저장소 필터는 두 갈래 모두에 걸립니다.

1 of selection_* 는 이름이 그 패턴에 맞는 선택들을 OR 로 묶습니다. 필터는 그 묶음 전체에 and not 으로 붙입니다. 목표는 실제 침해 4건입니다.

배포할 수 있는 규칙으로

6번 규칙에 id·status·description·author·date·references·falsepositives·level·tags 를 채워 /root/sigma/07-release.yml 에 쓰세요. 잡는 사건은 6번과 같아야 합니다.

id 는 UUID 꼴이어야 합니다(python3 -c 'import uuid;print(uuid.uuid4())'). status 는 아직 운영 자료로 돌려 보지 않은 규칙의 값을 고르고, level 은 역방향 셸까지 잡는 규칙에 맞게 정하세요. tags 에는 attack. 으로 시작하는 항목이 하나 이상 필요합니다.

숫자로 남긴다

3번과 7번 규칙을 진실 집합(실제 침해 4건)과 대조해 /root/sigma/08-review.md 에 적으세요. 규칙마다 한 줄에 파일 이름과 matched=·tp=·fp=·fn= 네 값을 적고, ## 판단 절에 120자 이상으로 무엇을 내보낼지와 그 이유를 쓰세요.

값은 --ids 결과와 진실 집합을 비교해 직접 세면 됩니다. 진실 집합은 5단계에서 찾은 두 건과 3단계에서 찾은 것 중 사내 저장소가 아닌 것을 합친 것입니다.