
보안 동아리 4인 팀으로 Linux EDR 에이전트를 만들었다. eBPF로 프로세스·파일·네트워크·메모리·DNS·네임스페이스 이벤트를 관찰하고, 규칙과 이벤트 상관 분석으로 의심 행위를 잡는 프로젝트다. 여기서는 기능을 나열하기보다 “탐지 아이디어”를 발표에서 검증 가능한 결과로 바꾼 과정을 정리한다.
나는 시스템 영역과 팀 리드를 맡았다. 커널 이벤트를 받아 처리하는 에이전트 쪽, 탐지 규칙 검증과 벤치마크, 격주 보고서와 일정 조율이 내 담당이었다. 프론트엔드·데모 화면·발표자료는 다른 팀원들의 기여가 컸고 최종 발표 준비는 나와 다른 팀원이 함께 했다.
팀 프로젝트 회고에서 모든 기능을 “내가 만들었다”고 쓰면 결과는 화려해 보여도 기록의 신뢰가 사라진다. 그래서 저장소 전체 기능과 내가 직접 맡은 부분을 나눠 적었다.
초반에는 “이런 행위를 탐지하면 좋겠다”는 아이디어가 계속 나왔다. 하지만 발표에서 필요한 것은 규칙 이름이 아니라 실제 이벤트가 발생했고 에이전트가 그 규칙을 발화했다는 증거다. 그래서 탐지 항목마다 최소 재현 시나리오를 붙였다.
예를 들어 임시 디렉터리에서 실행한 프로세스가 외부 연결을 만드는 흐름이라면, 파일 생성·실행·connect 이벤트가 같은 PID와 시간 창에서 연결되는지 확인한다. 단일 이벤트 한 줄만으로 공격이라고 단정하기보다 여러 이벤트의 순서가 맞을 때 상관 규칙을 발화하도록 했다.
eBPF 프로그램은 검증기와 실행 비용 제약을 받는다. 커널 쪽에는 이벤트 수집과 최소한의 파싱을 두고, 규칙 매칭·중복 억제·상관 분석·위협 인텔리전스 대조는 유저스페이스로 넘겼다. 현재 공개 저장소 기준으로 6개 BPF 프로그램이 ring buffer를 통해 이벤트를 보내고, 유저스페이스에서 28개 패턴을 처리한다.
이 분리는 기능을 더 넣기 위해서만 필요한 게 아니었다. 규칙을 YAML로 바꾸고, 정상 프로세스 화이트리스트를 조정하고, 이벤트가 너무 많이 들어올 때 중복 알림을 줄이는 작업을 커널 재빌드 없이 할 수 있었다.
EDR은 한 번 실행하고 끝나는 도구가 아니라 계속 켜두는 프로그램이다. 규칙이 잘 잡혀도 CPU와 메모리 사용량이 크거나 이벤트 손실이 심하면 실사용하기 어렵다. 그래서 탐지 시나리오와 함께 아래 항목을 기록했다.
Falco처럼 공개된 런타임 보안 도구가 규칙의 조건·출력·우선순위를 어떻게 분리하는지도 참고했다. 그대로 복제하지 않고, 우리 에이전트의 이벤트 구조에서 설정 파일로 바꿔야 할 값과 코드에 남겨야 할 로직을 구분하는 데 썼다.
구현이 적었던 회차도 회의에서 정한 역할, 막힌 이유, 다음 검증 항목을 보고서에 남겼다. 발표 직전에는 이 기록이 작업 분배와 누락 확인표가 됐다. 누가 어떤 기능을 맡았고 어떤 증거가 준비됐는지 바로 찾을 수 있었기 때문이다.
이 프로젝트에서 가장 크게 배운 건 탐지 아이디어를 내는 것보다 주장을 재현으로 바꾸는 일이 어렵다는 점이었다. 이벤트를 실제로 만들고, 알림을 확인하고, 오버헤드와 오탐까지 같이 기록해야 비로소 “동작한다”고 말할 수 있었다.
| 항목 | 기록 내용 |
|---|---|
| 재현 명령 | 통제된 VM에서 발생시킨 최소 행위 |
| 기대 이벤트 | exec, file, connect 등 커널 이벤트 |
| 기대 규칙 | 단일 규칙 또는 상관 규칙 ID |
| 관찰 결과 | 발화 여부·타임스탬프·PID 연결 |
| 정상 대조군 | 같은 도구의 정상 사용에서 오탐 여부 |
공격 명령 한 번으로 알림이 떴다고 끝내지 않았다. 정상 업데이트, 디버거, 컨테이너 런타임처럼 비슷한 이벤트를 만드는 대조군을 같이 실행했다. 이 과정에서 sshd, apt, dockerd, gdb 같은 정상 프로세스의 노이즈를 확인하고 화이트리스트와 상관 조건을 조정했다.
숫자가 예쁘게 나온 한 번만 고르지 않고 조건과 반복 횟수를 보고서에 남겼다. 그래야 다음 팀원이 규칙을 추가한 뒤 같은 방법으로 회귀를 확인할 수 있다.
탐지와 마찬가지로 퍼징 결과도 주장보다 재현 증거가 중요했다. 공개 제보 과정은 AFL++로 네트워크 포렌식 파서를 퍼징해 GHSA까지 간 기록에 정리했다.
| 취약점 심각도를 정직하게 매기기 — RCE라고 부풀리지 않으려고 한 일들 (0) | 2026.07.28 |
|---|---|
| SSH 끊어도 죽지 않는 퍼징 캠페인 만들기 (nohup은 왜 죽었나) (0) | 2026.07.28 |
| 오픈소스 취약점을 GitHub에 책임 있게 제보하기 — PVR이 없을 때 겪은 일들 (0) | 2026.07.27 |
| Boolean Blind SQLi로 한 글자씩 데이터 뽑아내기 — WHS 워게임 5단계 (0) | 2026.07.26 |
| AIxCC 우승 시스템 ATLANTIS·Crete 로컬 설치 후기 (1) | 2026.07.26 |