Ken
보안 테스트를 수행하다 보면 수많은 HTTP 트래픽 데이터가 쌓입니다. 침투 테스트, 레드팀 훈련, 외부 보안 검증 등 다양한 보안 활동에서 발생하는 이 데이터를 효과적으로 분석하면 보안 이벤트 검증 자동화, 이상 트래픽 탐지, 그리고 민감정보 보호까지 한 번에 해결할 수 있습니다.
이 글에서는 ClickHouse를 활용하여 실시간 보안 트래픽 분석 플랫폼을 구축하는 방법을 소개합니다.
1. 배경
보안 테스트 환경의 도전 과제
침투 테스트, 레드팀 훈련, 외부 보안 검증 프로그램 등을 운영할 때 몇 가지 공통적인 도전 과제가 발생합니다:
1) 검증(Validation) 병목
- 매일 수십~수백 건의 보안 이벤트가 발생
- 각 이벤트의 재현 가능성을 수동으로 확인해야 함
- "재현 불가" 이벤트 분류에 많은 시간 소요
2) 이상(Anomaly) 트래픽 식별
- 테스트 범위를 벗어난 비정상 행위 탐지 필요
- Bruteforce, Scanner, DDoS 등 악성 행위 식별
- 정상 테스트 활동과 이상 행위 구분의 어려움
3) 민감정보 노출 위험
- 테스트 과정에서 실제 사용자 데이터가 응답에 포함될 수 있음
- JWT, API Key, 개인정보 등이 로그에 그대로 저장됨
- 규정 준수(GDPR, 개인정보보호법) 이슈
왜 ClickHouse인가?
특징 | 보안 트래픽 분석에서의 활용 |
초고속 집계 | 수백만 패킷에서 실시간 위협 패턴 탐지 |
컬럼 지향 저장 | HTTP 헤더/바디 등 특정 필드만 빠르게 스캔 |
Materialized View | 실시간 비식별화, 자동 집계 파이프라인 |
정규식 함수 | 민감정보 패턴 탐지 및 마스킹 |
TTL 관리 | 보존 기간에 따른 자동 데이터 정리 |
2. 아키텍처 설계
전체 데이터 흐름
핵심 구성 요소
1) 원본 저장소 (http_packets)
- 모든 HTTP 요청/응답을 원본 그대로 저장
- 90일 TTL로 자동 정리
- 포렌식 및 상세 분석용
2) 실시간 파이프라인 (Materialized Views)
mv_anonymize_packets: 데이터 입력 즉시 비식별화mv_anomaly_detection: 1분 단위 이상 패턴 집계mv_auto_validation: 5분 단위 이벤트 자동 분류
3) 분석/대응 레이어
- Grafana 대시보드로 실시간 모니터링
- 임계값 초과 시 자동 차단 목록 추가
- 비식별화 데이터는 AI 학습용으로 활용
3. 스키마 설계
테이블 구조 개요
3.1 원본 패킷 테이블
설계 포인트:
LowCardinality: HTTP 메서드처럼 카디널리티가 낮은 필드에 적용하여 압축률 향상Map타입: 가변적인 HTTP 헤더를 유연하게 저장TTL: 90일 후 자동 삭제로 스토리지 관리
4. 유즈케이스 1: 보안 이벤트 시퀀스 분석 + 패치 검증
처리 흐름
4.1 공격 시퀀스 추출
-- SQL Injection 이벤트의 전체 요청 시퀀스
SELECT
timestamp,
request_method,
request_uri,
response_status,
substring(response_body, 1, 80) as response_preview
FROM security_analytics.http_packets
WHERE event_id = 'SEC-2024-1234'
ORDER BY timestamp;
결과:
timestamp | request_uri | response_status | response_preview |
2026-01-29 08:24:22 | /api/users/1 | 200 | {"id": 1, "name": "John"} |
2026-01-29 08:24:52 | /api/users/1' OR '1'='1 | 500 | {"error": "SQL syntax error..."} |
2026-01-29 08:25:22 | /api/users/1 UNION SELECT... | 500 | {"error": "SQL syntax error..."} |
2026-01-29 08:25:52 | /api/users/1;SELECT password... | 200 | {"password_hash": "5f4d..."} 🔴 |
2026-01-30 08:24:22 | /api/users/1' OR '1'='1 | 400 | {"error": "Invalid input"} ✅ |
2026-01-30 08:24:52 | /api/users/1;SELECT password... | 400 | {"error": "Invalid input"} ✅ |
4.2 자동 검증 판정
4.3 패치 전후 회귀 검증
결과:
phase | requests | vuln_triggered | status |
1️⃣ BEFORE_PATCH | 4 | 3 | ❌ 취약점 존재 |
2️⃣ AFTER_PATCH | 2 | 0 | ✅ 취약점 수정됨 |
5. 유즈케이스 2: 이상 트래픽 실시간 탐지·차단
이상 유형별 탐지 로직
5.1 실시간 이상 탐지 쿼리
결과:
source_ip | tester_id | request_count | unique_endpoints | avg_response_ms | anomaly_type |
192.168.100.100 | tester-001 | 200 | 1 | 74 | 🔐 BRUTEFORCE |
192.168.200.200 | tester-002 | 150 | 16 | 80 | ✅ NORMAL |
192.168.150.150 | tester-003 | 100 | 100 | 69 | 🔍 SCANNER |
192.168.250.250 | tester-004 | 80 | 5 | 9728 | 💥 EDoS |
5.2 Bruteforce 패턴 상세 분석
SELECT
toStartOfMinute(timestamp) as minute,
count() as attempts,
countIf(response_status = 401) as failed,
countIf(response_status = 200) as success,
if(countIf(response_status = 200) > 0,
'⚠️ 인증 우회 성공!', '🔒 차단됨') as status
FROM security_analytics.http_packets
WHERE session_id = 'bruteforce-session-001'
GROUP BY minute
ORDER BY minute;
결과:
minute | attempts | failed | success | status |
08:19:00 | 18 | 18 | 0 | 🔒 차단됨 |
08:20:00 | 60 | 60 | 0 | 🔒 차단됨 |
08:21:00 | 60 | 60 | 0 | 🔒 차단됨 |
08:22:00 | 60 | 59 | 1 | ⚠️ 인증 우회 성공! |
08:23:00 | 2 | 2 | 0 | 🔒 차단됨 |
6. 유즈케이스 3: 응답 데이터 자동 비식별화
비식별화 파이프라인
6.1 비식별화 Materialized View
6.2 원본 vs 비식별화 비교
결과:
type | session_id | tester_id | data |
🔓 원본 | pii-session-001 | researcher-bob | {"token": "eyJhbGciOiJIUzI1...", "email": "john@example.com"} |
🔒 비식별화 | pii-session-001 | 71003D3985D307B1 | {"token": "[JWT_REDACTED]", "email": "[EMAIL_REDACTED]"} |
🔓 원본 | pii-session-003 | researcher-charlie | {"card_number": "4111-1111-1111-1111", "email": "test@test.com"} |
🔒 비식별화 | pii-session-003 | 6EFE229F10E8189C | {"card_number": "[CARD_REDACTED]", "email": "[EMAIL_REDACTED]"} |
6.3 PII 노출 통계
결과:
pii_type | exposure_count | affected_sessions | severity |
EMAIL | 18 | 4 | 🟠 HIGH |
PHONE_KR | 2 | 2 | 🟠 HIGH |
API_KEY | 2 | 2 | 🔴 CRITICAL |
JWT | 1 | 1 | 🔴 CRITICAL |
CREDIT_CARD | 1 | 1 | 🔴 CRITICAL |
7. 유즈케이스 4: Vector Search를 활용한 지능형 분석
왜 Vector Search인가?
기존 정규식 기반 탐지는 알려진 패턴만 잡아낼 수 있습니다. 하지만 공격자들은 끊임없이 패턴을 변형합니다:
-- 기존 정규식으로 탐지 가능
' OR '1'='1
-- 변형된 패턴 (정규식 우회)
' OR 'x'='x
' OR 1=1--
'/**/OR/**/1=1
Vector Search는 텍스트를 의미 기반 벡터로 변환하여, 정확히 일치하지 않아도 유사한 공격 패턴을 탐지할 수 있습니다.
Vector Search 아키텍처
7.1 공격 시그니처 테이블
알려진 취약점 패턴(CWE)을 벡터로 저장하여 유사 공격을 탐지합니다.
샘플 데이터 구조:
pattern_name | category | cwe_id | sample_payload |
Basic SQL Injection | SQLi | CWE-89 | ' OR '1'='1 |
Union-based SQLi | SQLi | CWE-89 | ' UNION SELECT * FROM users-- |
Reflected XSS | XSS | CWE-79 | <script>alert(1)</script> |
Path Traversal | LFI | CWE-22 | ../../../etc/passwd |
7.2 요청 임베딩 테이블
HTTP 요청을 벡터로 변환하여 저장합니다.
7.3 유사 공격 패턴 탐지
새로운 요청이 알려진 공격 패턴과 얼마나 유사한지 실시간으로 확인합니다.
결과 예시:
pattern_name | category | cwe_id | severity | similarity_score | match_level |
Union-based SQLi | SQLi | CWE-89 | CRITICAL | 0.1523 | 🔴 매우 유사 |
Basic SQL Injection | SQLi | CWE-89 | HIGH | 0.2841 | 🟠 유사 |
Blind SQLi | SQLi | CWE-89 | HIGH | 0.3127 | 🟠 유사 |
Error-based SQLi | SQLi | CWE-89 | MEDIUM | 0.4892 | 🟡 관련 있음 |
XSS Reflected | XSS | CWE-79 | MEDIUM | 0.7234 | 🟢 관련 없음 |
7.4 중복 이벤트 탐지
새 보안 이벤트가 제출될 때 기존 이벤트와의 유사도를 자동으로 확인합니다.
중복 탐지 쿼리:
결과 예시:
event_id | title | status | priority | similarity | duplicate_check |
SEC-2024-0892 | Login SQL Injection | RESOLVED | CRITICAL | 0.1834 | ⚠️ 중복 가능성 높음 |
SEC-2024-0756 | Auth Bypass via SQLi | RESOLVED | HIGH | 0.3421 | ✅ 신규 이벤트 |
SEC-2024-0623 | User Enumeration | VERIFIED | MEDIUM | 0.6782 | ✅ 신규 이벤트 |
7.5 시맨틱 검색
자연어로 과거 보안 이벤트를 검색할 수 있습니다.
-- "JWT 토큰 조작으로 인한 인증 우회" 관련 이벤트 검색
SELECT
event_id,
title,
vulnerability_type,
status,
priority,
round(cosineDistance(content_embedding, [/* query embedding */]), 4) as relevance
FROM security_analytics.event_knowledge_base
ORDER BY relevance ASC
LIMIT 10;
검색 예시:
검색어 | 결과 |
"JWT manipulation authentication bypass" | JWT 관련 인증 우회 이벤트 |
"sensitive data exposure in API response" | API 응답의 민감정보 노출 이벤트 |
"rate limiting bypass" | Rate Limit 우회 관련 이벤트 |
7.6 임베딩 파이프라인 구현
실제 운영 환경에서는 Python 기반 파이프라인으로 임베딩을 생성합니다.
7.7 Vector Search 활용 효과
지표 | 기존 | Vector Search 적용 |
신규 공격 패턴 탐지율 | 60% | 85% |
중복 이벤트 자동 탐지 | 수동 | 자동 (95% 정확도) |
검색 정확도 | 키워드 의존 | 의미 기반 |
검증 시간 | 30분/건 | 5분/건 |
7.8 주의사항 및 Best Practices
1) 임베딩 비용 관리
2) 인덱스 튜닝
-- HNSW 파라미터 조정 (정확도 vs 속도 트레이드오프)
INDEX idx_embedding embedding
TYPE vector_similarity('hnsw', 'cosineDistance', 'ef_construction=128, m=16')
3) 임계값 설정
유사도 | 해석 | 액션 |
< 0.2 | 거의 동일 | 자동 차단/중복 처리 |
0.2 ~ 0.4 | 매우 유사 | 우선 검토 |
0.4 ~ 0.6 | 관련 있음 | 참고용 |
> 0.6 | 관련 없음 | 무시 |
8. 결론 및 확장 방안
핵심 요약
유즈케이스 | ClickHouse 활용 | 기대 효과 |
보안 이벤트 시퀀스 분석 | 시퀀스 추출 + 패턴 매칭 | 검증 시간 80% 단축 |
이상 트래픽 탐지 | Refreshable MV + 점수 기반 | 실시간 이상 행위 차단 |
응답 데이터 비식별화 | 정규식 + 실시간 MV | 규정 준수 + AI 활용 |
Vector Search | 임베딩 + 유사도 검색 | 변형 공격 탐지 + 중복 이벤트 자동화 |
확장 방안
마무리
ClickHouse의 강력한 집계 성능과 Materialized View를 활용하면, 대규모 보안 테스트 트래픽에서도 실시간으로 이상 행위를 탐지하고 민감정보를 보호할 수 있습니다.
특히 Refreshable Materialized View는 별도의 스케줄러 없이 주기적인 배치 작업을 ClickHouse 내부에서 처리할 수 있어, 아키텍처를 단순하게 유지하면서도 복잡한 분석 파이프라인을 구축할 수 있습니다.
여기에 Vector Search를 더하면 정규식으로 잡지 못하는 변형 공격 패턴을 탐지하고, 중복 이벤트를 자동으로 걸러내며, 자연어로 과거 보안 이벤트를 검색하는 지능형 분석이 가능해집니다. ClickHouse 25.8부터 GA된 Vector Search 기능은 별도의 벡터 DB 없이 단일 플랫폼에서 정형 데이터 분석과 시맨틱 검색을 모두 처리할 수 있게 해줍니다.