[Cloud & CERT] 조사 3. CERT 인프라 설계 (박진혁)[Cloud & CERT] 조사 3. CERT 인프라 설계 (박진혁)

[Cloud & CERT] 조사 3. CERT 인프라 설계 (박진혁)

생성 일시
Sep 27, 2026 11:28 AM
최종 편집 일시
Last updated September 27, 2026
태그
작성자
@박진혁
Date

목차

  1. Mission 1. 서버에서 무슨 일이 일어났는지 알아내라
  1. Mission 2. 여러 대의 로그를 한곳에서 보고 싶다
  1. Mission 3. 이 IP가 공격자인지 어떻게 판단할 것인가
  1. Mission 4. 공격자를 발견했다, 이제 무엇을 할 것인가
  1. Mission 5. 사고를 조사하라
  1. 최종 CERT 구조와 도구 선택
  1. 정리하며

과제 1에서 서비스 구조를, 과제 2에서 네트워크를 만들었다. 둘 다 막는 쪽의 설계였다. 과제 3은 반대쪽이다. 막지 못했을 때 무슨 일이 일어났는지 알아내고, 판단하고, 대응하는 구조를 만든다.
시작할 때 CERT가 정확히 뭘 하는 조직인지도 잘 몰랐다. 조사해 보니 Computer Emergency Response Team, 즉 침해 사고를 탐지하고 대응하는 팀이고, 이 과제는 그 팀이 일하려면 평소에 어떤 인프라가 깔려 있어야 하는가를 만드는 것이었다. 이 문장이 과제 전체의 핵심이었다.

Mission 1. 서버에서 무슨 일이 일어났는지 알아내라

Step 1. 사고 난 뒤에 들어가 봤더니 아무것도 없다

문제 새벽 03:12에 실행된 프로세스는 이미 종료됐다. ps에도 없고 history도 비어 있다.
여기서 배운 게 사후 조사와 상시 수집의 차이다. ps, netstat, history 같은 명령은 전부 지금 이 순간의 상태를 보여 준다. 프로세스가 끝나면 흔적이 사라지고, history는 공격자가 지울 수 있으며, 애초에 대화형 셸이 아니면 남지도 않는다. 사고가 난 뒤에 들어가서 보는 건 이미 지나간 시점을 복원하려는 시도라 한계가 분명했다.
그래서 필요한 게 Endpoint Telemetry, 즉 서버에서 일어나는 행위를 평소에 계속 기록해 두는 것이다. 문제에서 물은 네 가지를 알려면 각각 이런 게 필요했다.
알고 싶은 것
수집해야 하는 것
리눅스에서의 수단
누가
인증·권한 상승 기록, UID
auth.log, sudo 로그, auditd
무슨 명령
프로세스 실행 이벤트 (실행 파일, 인자, 부모 프로세스)
auditd execve, eBPF
어떤 파일
파일 생성·수정·삭제, 무결성 변화
auditd watch, FIM
어떤 IP
아웃바운드 연결, 목적지와 포트
conntrack, eBPF, VPC Flow Logs
기록할 때 부모 프로세스(PPID)를 같이 남겨야 한다는 점이 인상적이었다. "이상한 프로세스가 실행됐다"보다 "웹 서버 프로세스가 셸을 실행했고 그 셸이 이 프로세스를 실행했다"가 훨씬 많은 걸 말해 준다. 실행 계보가 곧 침투 경로의 단서다.

Step 2. 서버가 5대면 5대를 각각 뒤져야 한다

문제 게다가 공격자가 서버 권한을 가졌으면 기록도 지울 수 있다.
기록을 남기기 시작하니 두 가지 문제가 새로 생겼다. 서버마다 따로 들어가 봐야 한다는 것, 그리고 그 기록이 공격자와 같은 서버에 있다는 것이다. 두 번째가 더 심각하다. 공격자가 root를 잡으면 자기 흔적을 지울 수 있으니, 기록이 곧 증거가 되려면 공격자 손이 닿지 않는 곳에 실시간으로 내보내야 한다.
이 역할을 하는 게 EDR(Endpoint Detection & Response)이다. 이름 그대로 엔드포인트에서 탐지하고 대응까지 한다. 에이전트가 각 서버에 상주하면서 행위를 수집해 중앙 서버로 보내고, 중앙에서 여러 서버를 한 번에 조회하거나 프로세스 종료, 격리 같은 조치를 내릴 수 있다. 사고가 난 뒤 증거를 수집하고 분석하는 분야를 DFIR(Digital Forensics & Incident Response)이라고 부른다는 것도 이때 알았다.
조사한 오픈소스는 이렇다.
  • Wazuh — 에이전트 기반으로 로그 수집, 파일 무결성 감시, 룰 기반 탐지를 한다. 뒤에 나올 SIEM 역할까지 겸한다.
  • osquery — 서버 상태를 SQL로 조회할 수 있게 해 준다. "지금 이 포트를 열고 있는 프로세스"를 전 서버에 한 번에 질의할 수 있다.
  • Velociraptor — 원격에서 다수의 엔드포인트를 조사하고 아티팩트를 수집하는 DFIR 도구다.
  • Falco — 시스템 콜 기반 런타임 탐지. 컨테이너 환경에 강하다.
여기서 처음에 잘못 생각한 게 있다. EDR과 SIEM을 같은 것으로 봤다. 조사해 보니 EDR은 엔드포인트 안에서 일어나는 행위를 보는 도구이고, SIEM은 여러 출처의 로그를 모아 상관관계를 보는 도구다. Wazuh처럼 둘을 겸하는 제품이 있어서 헷갈렸는데, 역할이 다르다는 걸 구분하고 나니 뒤의 Mission이 훨씬 잘 읽혔다.

Mission 2. 여러 대의 로그를 한곳에서 보고 싶다

Step 3. 공격 하나 추적하는 데 SSH를 네 번 한다

문제 서버마다 시간대와 로그 형식이 다르다.
로그를 한곳에 모으는 Centralized Logging으로 해결되는 건 세 가지다. 서버를 옮겨 다니지 않아도 되고, 공격자가 지울 수 없는 곳에 사본이 생기고, 여러 서버를 가로질러 한 번에 검색할 수 있다.
다만 그냥 모으기만 하면 안 된다는 게 이 Step의 진짜 내용이었다.
Log Normalization은 형식이 제각각인 로그를 공통 필드로 맞추는 작업이다. Nginx는 remote_addr, 방화벽은 src_ip, CloudTrail은 sourceIPAddress로 같은 걸 부른다. 이걸 source.ip 같은 공통 이름으로 통일해야 "이 IP가 등장하는 모든 로그"를 한 번에 검색할 수 있다. ECS(Elastic Common Schema)나 OCSF 같은 표준 스키마를 쓴다는 것도 알게 됐다.
NTP는 더 기본적이다. 서버 시계가 몇 초씩 어긋나 있으면 사건의 순서가 뒤집힌다. 방화벽 로그가 웹 로그보다 늦게 찍히면 "차단 후 접속"이라는 말이 안 되는 타임라인이 나온다. 모든 서버를 같은 NTP 서버에 맞추고, 로그는 UTC로 저장하고 볼 때 KST로 변환하는 게 원칙이었다. Mission 5의 타임라인이 성립하려면 이 Step이 먼저 되어 있어야 한다.

Step 4. 하루 수백만 줄, 사람이 못 읽는다

문제 모아두기만 했지 뭐가 이상한지 알려주지 않는다.
저장과 탐지는 다르다. 저장은 나중에 찾아볼 수 있게 두는 것이고, 탐지는 "이건 이상하다"고 지금 알려 주는 것이다. 로그를 모은 것만으로 보안이 된 게 아니었다.
"이상하다"의 기준은 결국 사람이 탐지 룰(Detection Rule)로 정의해야 한다. 조사한 방식은 세 가지였다.
  • 시그니처 기반 — 알려진 패턴에 맞으면 경보. 명확하지만 새로운 공격은 못 잡는다.
  • 임계치 기반 — "5분에 로그인 실패 20회" 같은 횟수 기준. 단순하지만 천천히 하는 공격은 놓친다.
  • 이상 행위 기반 — 평소와 다른 패턴. 넓게 잡지만 오탐이 많다.
  • *SIEM(Security Information and Event Management)이 이 역할을 한다. 로그 수집과 정규화, 저장, 룰 기반 탐지, 경보 발생까지가 SIEM의 범위였다.
이 Step에서 또 하나 잘못 생각했던 걸 발견했다. 나는 "로그를 모으면 알아서 탐지가 되는 줄" 알았다. 실제로는 탐지 룰이 없으면 SIEM은 그냥 검색 가능한 로그 창고다. 뭘 위협으로 볼지 정하는 건 끝까지 사람의 일이었다.

Step 5. 알림이 따로따로 와서 같은 공격인지 모른다

문제 Firewall에서 막힌 IP와 Web 로그인 실패 IP가 같다는 걸 사람이 눈으로 맞춰야 한다.
필요한 건 Correlation(상관분석)이다. 서로 다른 출처의 이벤트를 하나의 공격으로 묶으려면 공통으로 잡을 축이 있어야 하는데, 조사해 보니 보통 이런 것들이었다.
  • 공통 필드 — 같은 Source IP, 같은 계정, 같은 파일 해시, 같은 호스트
  • 시간 창 — "10분 안에 일어난 일들"로 묶기
  • 순서 — 로그인 실패 다발 → 로그인 성공 → 권한 상승처럼 순서가 의미를 갖는 조합
여기서 Step 3의 정규화가 왜 먼저였는지 확실히 이해됐다. 필드 이름이 통일되어 있지 않으면 공통 축으로 묶는 것 자체가 불가능하다. 정규화는 검색 편의가 아니라 상관분석의 전제 조건이었다.
상관분석까지 제공하는 오픈소스로는 Wazuh(룰 그룹과 if_matched_sid 같은 조건으로 연계 룰 작성), Elastic Security, Graylog를 봤다. 탐지 룰을 특정 제품 문법이 아니라 공통 형식으로 쓰는 Sigma도 여기서 다시 나왔다. 1회차에 조사했던 Detection-as-Code가 바로 이 룰들을 Git으로 관리하는 방식이다.

Mission 3. 이 IP가 공격자인지 어떻게 판단할 것인가

Step 6. 우리 로그만으로는 알 수 없다

문제 185.xxx.xxx.xxx가 공격자인지 해외 고객인지 whois로는 국가만 나온다.
우리 로그는 "이 IP가 우리에게 무엇을 했는가"만 안다. "이 IP가 다른 곳에서 무엇을 했는가"는 우리 데이터 밖에 있다. 그 바깥 정보가 Threat Intelligence다.
IP Reputation은 특정 IP가 과거에 스캔, 브루트포스, 스팸, C2 통신 등에 쓰였는지에 대한 평판 정보다. 받아오는 경로는 이렇게 정리했다.
  • 공개 피드 — AbuseIPDB, Spamhaus, Tor exit node 목록, Feodo Tracker 등
  • 조회형 API — VirusTotal, GreyNoise (인터넷 전역 스캐너인지 표적 공격인지 구분해 준다)
  • 국내 공유 체계 — KISA C-TAS 같은 침해 정보 공유 체계
  • 표준 포맷 — STIX로 표현하고 TAXII로 주고받는 구조가 사실상 표준이었다
조사하면서 알게 된 중요한 점은, TI는 판단을 대신해 주는 게 아니라 판단의 재료라는 것이다. "악성으로 신고된 적 있음"은 "지금 우리를 공격하는 중"과 다르다. 이 구분이 Step 10에서 실제 사고로 이어진다.

Step 7. 받아온 정보와 우리 로그를 어떻게 비교하나

받아온 정보에서 "이게 나오면 악성"이라고 판단할 수 있는 단위를 IOC(Indicator of Compromise)라고 한다. IP, 도메인, URL, 파일 해시, 이메일 주소, 레지스트리 키 같은 것들이다.
SIEM과 연결하는 방식은 두 가지로 정리했다.
  • 유입 시점 대조 — 로그가 들어올 때마다 IOC 목록과 맞춰 보고 일치하면 경보. 빠르지만 IOC 목록이 클수록 부담이다.
  • 소급 검색(Retro hunt) — 새 IOC를 받으면 과거 로그를 거슬러 검색한다. "3주 전에 이미 통신한 적 있었다"를 찾아낼 수 있다.
두 번째가 특히 중요해 보였다. IOC는 사건이 벌어진 뒤에 공개되는 경우가 많아서, 새 IOC로 과거를 다시 훑지 않으면 이미 당한 사실을 영영 모를 수 있다.
그리고 IOC에는 수명이 있다는 점도 알게 됐다. IP는 재할당되고, 도메인은 주인이 바뀐다. 오래된 IOC를 계속 들고 있으면 오탐이 된다. 반면 파일 해시는 바뀌지 않지만 공격자가 바이트 하나만 고쳐도 무력화된다. 그래서 IOC 종류마다 신뢰도와 유효 기간을 따로 관리해야 한다.

Step 8. 소스마다 형식도 다르고 판단도 다르다

문제 같은 IP가 한쪽에서는 악성, 다른 쪽에서는 없다.
이걸 정리하는 역할이 TIP(Threat Intelligence Platform)다. 여러 소스의 IOC를 모아 형식을 정규화하고, 중복을 합치고, 신뢰도와 유효 기간을 관리하고, SIEM이나 차단 장비로 내보낸다.
오픈소스로는 MISP(IOC 공유와 상관분석에 특화, 국내외 공유 체계와 연동이 많다)와 OpenCTI(IOC뿐 아니라 공격자 그룹, 캠페인, TTP까지 지식 그래프로 관리)를 조사했다.
소스가 엇갈릴 때의 원칙도 정리했다. 여러 소스에서 겹치면 신뢰도를 올리고, 한 소스에만 있으면 낮춘다. 소스별로 가중치를 두고, 최근에 관측된 것일수록 높게 본다. 그리고 우리 조직의 IP나 파트너 IP는 아예 화이트리스트로 제외해 둔다. 이 마지막 항목이 없어서 터지는 게 바로 다음 Mission이다.

Mission 4. 공격자를 발견했다, 이제 무엇을 할 것인가

Step 9. 새벽 3시에 탐지, 아침 9시에 차단

문제 6시간 동안 공격자는 자유로웠다.
침해 사고 대응(Incident Response)은 보통 이런 단계로 나뉜다는 걸 조사했다. 준비 → 탐지 및 분석 → 봉쇄(Containment) → 제거(Eradication) → 복구(Recovery) → 사후 검토. 이 중 시간이 가장 중요한 게 봉쇄다. 공격자가 자유로운 시간이 곧 피해 범위이기 때문이다.
사람이 개입하지 않고 탐지에서 차단까지 이어지려면 필요한 건 세 가지였다.
  • 기계가 읽을 수 있는 판단 결과 — "악성으로 판단됨"이 사람이 읽는 알림이 아니라 구조화된 이벤트여야 한다.
  • 조치를 실행할 수 있는 권한과 수단 — Security Group 규칙 변경, WAF 차단 목록 추가, 세션 종료 같은 API
  • 그 둘을 잇는 자동화 경로 — 이벤트를 받아 정해진 절차를 실행하는 무언가
AWS로 치면 GuardDuty Finding을 EventBridge가 받아 Lambda가 Security Group이나 NACL을 고치는 형태다.

Step 10. 자동 차단이 사무실 IP를 막았다

문제 위협 정보 소스 하나가 사무실 공인 IP를 잘못 등록했고, 팀원 전원이 차단됐다.
자동화의 대가가 여기서 나왔다. 오탐(False Positive)도 자동으로, 즉시, 전면적으로 실행된다. 사람이 하면 "어? 이거 우리 IP인데" 하고 멈추는 지점을 기계는 그냥 지나간다.
그래서 자동 차단의 기준을 이렇게 정리했다.
  • 신뢰도(Confidence) — 여러 소스에서 일치하고 최근 관측된 IOC만 자동 조치 대상으로 본다.
  • 차단 대상의 성격 — 서버 대역, 클라우드 사업자 IP, Tor exit처럼 정상 사용자가 있을 리 없는 대역은 자동으로 막아도 피해가 작다. 반대로 통신사 대역은 고객이 섞여 있을 수 있다.
  • 되돌릴 수 있는가 — TTL을 두고 자동 해제되게 하면 오탐 피해가 짧게 끝난다.
  • 화이트리스트 — 자사 IP, 사무실 IP, 파트너, 모니터링 서비스는 무조건 제외한다.
  • 조치의 강도 — 전면 차단 대신 특정 포트만 막기, 속도 제한, 세션 종료처럼 단계를 나눌 수 있다.
오탐의 피해는 사용자와 운영팀이 감당한다는 것도 이 Step의 답이었다. 보안팀은 "막아서 안전해졌다"고 생각하지만, 실제로는 서비스 장애와 같은 형태로 나타난다. 그래서 자동 차단 기준은 보안팀 혼자 정할 게 아니라 운영팀과 합의해야 하는 사항이었다.

Step 11. 어디까지 자동으로, 어디부터 사람이

문서가 아니라 시스템으로 만들려면 SOAR(Security Orchestration, Automation and Response)가 필요하다. 탐지 이벤트를 받아 정해진 플레이북(Playbook)대로 조사와 조치를 실행하고, 필요한 지점에서 사람의 승인(Approval)을 기다리는 도구다.
분기 기준은 이렇게 잡았다.
구분
조건
조치
자동 실행
고신뢰 IOC, 서버 대역, 되돌리기 쉬움
즉시 차단, TTL 24시간
자동 + 사후 통보
중간 신뢰도, 영향 범위 작음
속도 제한 후 슬랙 통보
사람 승인 필요
고객 트래픽 포함, 계정 정지, 인스턴스 격리
슬랙 승인 버튼 후 실행
자동 금지
프로덕션 서버 종료, 데이터 삭제
사람이 직접
오픈소스는 Shuffle(워크플로 기반 SOAR, 승인 단계 구성 가능)과 TheHive + Cortex(케이스 관리와 분석기 연동)를 조사했다. 1회차에 팀에서 조사한 SecOps 후보 구성과 그대로 이어지는 내용이었다.

Mission 5. 사고를 조사하라

Step 12. 기록이 세 군데에 흩어져 있다

문제 어떤 순서로 무엇이 일어났는지, 공격자가 어디까지 갔는지 한 줄로 설명이 안 된다.
Incident Timeline을 만들려면 필요한 게 세 가지였다. 통일된 시간 기준(Mission 2의 NTP), 사건을 잇는 공통 축(IP, 계정, 호스트, 프로세스 계보), 그리고 각 사건의 근거가 되는 원본 로그다.
각 단계를 공격 전술 단위로 분류하는 기준이 MITRE ATT&CK이다. 공격자의 행위를 전술(무엇을 하려 했는가)과 기법(어떻게 했는가)으로 나눈 지식 체계다. 이걸 쓰면 얻는 게 두 가지였다. 서로 다른 사고를 같은 언어로 비교할 수 있고, 비어 있는 칸이 곧 탐지 공백으로 드러난다.
여기서도 하나 잘못 생각했다. 나는 타임라인이 그냥 시간순 나열인 줄 알았다. 그런데 과제가 요구한 건 각 줄마다 "어느 도구의 어떤 로그로 확인했는가"를 붙이는 것이었다. 근거 없는 타임라인은 추측이고, 그건 보고서가 아니라 소설이다.

사고 타임라인

문제에 주어진 사건을 정리하면 이렇게 된다.
시각
사건
ATT&CK 전술
근거 데이터
03:05
외부 IP에서 웹 애플리케이션에 비정상 요청
Initial Access
Web access log, WAF log
03:12
Application Server에서 의심 프로세스 실행 (부모: 웹 서버 프로세스)
Execution
EDR 프로세스 이벤트, auditd execve
03:14
외부 IP로 아웃바운드 연결 발생
Command & Control
EDR 네트워크 이벤트, VPC Flow Logs, 방화벽 로그
03:17
의심 파일 생성 및 실행 권한 부여
Persistence
EDR 파일 이벤트, 파일 무결성 감시(FIM)
03:23
다른 서버로 접근 시도
Lateral Movement
대상 서버 auth.log, SIEM 상관 룰, Security Group 거부 로그
03:25
해당 IP 차단 및 인스턴스 격리
Containment
SOAR 실행 기록, Security Group 변경 이력, CloudTrail
03:05 줄은 문제에 없지만, Initial Access가 비어 있으면 "어떻게 들어왔는지 모른다"가 되기 때문에 이 칸을 채우는 게 조사의 핵심이라고 봤다. 반대로 채우지 못하면 그 자체가 탐지 공백으로 기록되어야 한다.

Step 13. 다음 사고 때 이 과정을 재현할 수 있어야 한다

조사 과정과 근거를 남기는 역할이 Case Management다. 사고 하나를 케이스로 만들고, 그 안에 타임라인, 수집한 아티팩트, 실행한 분석, 판단과 근거, 담당자와 시각을 함께 기록한다. 오픈소스로는 TheHive와 DFIR-IRIS를 조사했다.
  • *Chain of Custody(증거 보관 연속성)는 증거가 수집된 시점부터 누가 언제 어떻게 다뤘는지 끊기지 않고 기록되어야 한다는 원칙이다. 수집 시각과 수집자, 해시값, 보관 위치, 접근 이력을 남긴다. 법적 대응까지 갈 경우 증거로서의 효력이 여기에 달려 있고, 법까지 가지 않더라도 "왜 그렇게 판단했는가"를 나중에 검증할 수 있게 해 준다.
1회차에 조사했던 Detection-as-Code가 여기서 다시 연결됐다. 탐지 룰을 Git으로 관리하면 "이 경보가 왜 울렸는지"를 당시 룰 버전으로 되짚을 수 있다. 조사 재현성은 케이스 기록만이 아니라 탐지 쪽 이력 관리와 같이 가야 성립했다.

최종 CERT 구조와 도구 선택

Mission 1부터 4까지 쌓인 구조를 합치면 이렇게 된다.역할별 도구 후보와 선택 이유는 이렇게 정리했다.
역할
후보
선택
이유
엔드포인트 수집·탐지
Wazuh, osquery, Velociraptor, Falco
Wazuh
에이전트 수집, 파일 무결성, 룰 탐지, SIEM 기능이 한 제품에 있어 소규모 팀에 맞는다
컨테이너 런타임 탐지
Falco, Tetragon
Falco
k3s 환경에서 시스템 콜 단위 행위를 보려면 별도로 필요하다
로그 중앙화·상관분석
Wazuh, Elastic, Graylog
Wazuh
위와 같은 이유. 다만 대용량 검색은 별도 인덱서 구성이 필요하다
탐지 룰 형식
Sigma, 제품 고유 문법
Sigma
제품에 묶이지 않고 Git으로 관리하기 쉽다
위협 정보
MISP, OpenCTI, 공개 피드 직접 연동
MISP
IOC 관리와 공유 체계 연동에 집중되어 있어 범위가 명확하다
자동 대응
Shuffle, TheHive+Cortex, Lambda 직접 구현
Shuffle
승인 단계를 워크플로로 표현할 수 있어 Step 11의 요구와 맞는다
케이스 관리
TheHive, DFIR-IRIS
DFIR-IRIS
타임라인과 근거 기록이 중심이라 Mission 5 요구에 직접 대응한다
ㅤ
ㅤ
ㅤ
ㅤ
클라우드 환경이라 여기에 하나가 더 붙는다. GuardDuty는 AWS 계정 수준의 악성 행위를 관리형으로 탐지해 주므로, 자체 구축한 SIEM과 비교 기준으로 쓸 수 있다. Finding을 EventBridge로 받아 SOAR로 넘기면 Mission 4의 자동화 경로가 그대로 성립한다.

정리하며

과제 3에서 가장 크게 바뀐 생각은 "탐지 인프라는 사고가 나기 전에 깔려 있어야 의미가 있다"는 것이다. Mission 1의 첫 문제가 정확히 그것이었다. 사고가 난 뒤에 서버에 들어가 봐야 이미 늦고, 평소에 기록하고 있지 않으면 복원할 수 없다.
그리고 각 Mission이 전부 "모았다"와 "판단했다"의 간극을 메우는 과정이었다. 기록을 남겼다고 조사가 되는 게 아니었고(Mission 1의 Step 2), 로그를 모았다고 탐지가 되는 게 아니었고(Step 4), 탐지했다고 공격자인지 아는 게 아니었고(Mission 3), 판단했다고 막히는 게 아니었다(Mission 4). 매번 한 칸씩 부족한 지점에서 다음 도구가 나왔다.
잘못 생각했던 건 네 가지다. EDR과 SIEM을 같은 걸로 본 것, 로그를 모으면 알아서 탐지되는 줄 안 것, 자동 차단은 빠를수록 좋다고 본 것, 타임라인이 시간순 나열이면 된다고 생각한 것이다. 특히 세 번째는 Step 10에서 직접 대가를 봤다. 자동화는 판단을 빠르게 하는 게 아니라 판단을 그대로 증폭시킨다.