LabHub
学习 学习路径 课程

cron 在凌晨三点执行了 curl

一条规则改写六次

在 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단계에서 찾은 것 중 사내 저장소가 아닌 것을 합친 것입니다.