본문으로 건너뛰기

© 2026 Molayo

Dev.to헤드라인2026. 06. 27. 02:12

근실시간 공격 탐지를 위한 API 로그 분석에서의 로컬 LLM 활용

요약

Ollama를 활용해 로컬 LLM(qwen2.5-coder:1.5b)으로 API 로그를 분석하여 문맥 기반 공격을 탐지하는 PoC를 소개합니다. 기존 규칙 기반 WAF가 놓치기 쉬운 IDOR와 같은 의미론적 공격을 실시간에 가깝게 식별하는 방법을 다룹니다.

핵심 포인트

  • Ollama를 통한 로컬 LLM 기반의 API 로그 분석 구현
  • 정규 표현식 및 시그니처 기반 탐지의 한계 극복
  • IDOR 등 문맥(Context) 중심의 의미론적 공격 탐지 가능성 확인
  • 소형 모델을 활용한 근실시간 보안 분석 프로세스 제안

실용적인 개념 증명 (PoC): Ollama를 통해 소형 언어 모델 (qwen2.5-coder:1.5b)을 로컬에서 실행하여 REST API의 로그를 검사하고, WAF(Web Application Firewall) 및 정적 규칙을 우회하는 IDOR와 같은 의미론적 공격을 포함한 공격을 탐지합니다.

이 POC에 사용된 프로젝트는 여기에서 확인할 수 있습니다:

github -> https://github.com/R9n/api-logs-llm-analyze

1. 서론

최근 몇 년 동안 인공지능 (AI)은 먼 미래의 약속에서 소프트웨어 엔지니어링의 일상적인 부분으로 변모했습니다. 코드 생성, 자동화된 풀 리퀘스트 (Pull Request) 리뷰, 문서화 지원, 합성 테스트 — SDLC (Software Development Life Cycle, 소프트웨어 개발 생명 주기)에서 LLM (Large Language Models, 거대 언어 모델)의 채택 곡선은 거의 기하급수적으로 성장했습니다. 한때 전문 도구와 전담 팀이 필요했던 작업들을 이제는 개인용 컴퓨터에서 오후 시간 동안 프로토타입으로 만들어 볼 수 있습니다.

이러한 흐름은 방어적 보안 (AppSec, Application Security) 측면에서도 흥미롭고 (동시에 모호한) 장을 열어줍니다. 한편으로는, 우리는 새로운 종류의 "분석가"를 얻게 됩니다. 즉, 비정형 텍스트를 읽고, 문맥을 이해하며, 의도에 대해 추론할 수 있는 모델입니다. 이는 고정된 패턴에 기반한 도구들이 결코 잘 수행할 수 없었던 영역입니다. 다른 한편으로는, AI 자체가 새로운 위험을 초래합니다. 프롬프트 인젝션 (Prompt Injection), 프롬프트 내 민감한 데이터 유출, 거짓 양성 (False Positives)을 생성하는 환각 (Hallucinations), 그리고 대규모 추론을 위한 값비싼 인프라에 대한 의존성 등이 그것입니다.

이 논쟁의 중심에는 오래되었으면서도 점점 더 심각해지는 문제, 즉 **방대한 양의 API 로그를 어떻게 실시간으로 모니터링할 것인가?**라는 문제가 자리 잡고 있습니다. 현대의 애플리케이션은 분당 수천 줄의 로그를 생성합니다. 그중 대부분은 정상적인 운영상의 노이즈입니다. 하지만 그 흐름 속에는 공격의 징후들이 숨어 있습니다. 일련의 로그인 시도, 바뀐 ID, 노출된 디버그 엔드포인트 등이 그것입니다. 이러한 신호들을 수동으로 찾는 것은 불가능하며, 뒤에서 살펴보겠지만 기존의 도구들은 **시그니처 (Signature)**가 아닌 **문맥 (Context)**에 의존하는 공격을 탐지하는 데 구조적인 한계를 가지고 있습니다.

이 글에서는 LLM과 단순하지만 빠른 모델을 사용하여 문맥 기반 공격을 식별하는 방법을 시도하며 이 아이디어를 조금 더 탐구해 보겠습니다.

2. 제안된 접근 방식 및 목표

이 연구의 **핵심 (Core)**은 설명하기는 간단하지만 실행하기는 까다롭습니다. 바로 **로컬 LLM (Local LLM)**을 자동화된 보안 분석가로 실행하여, REST API의 로그를 시간 창(Time windows) 단위로 입력하고, (근)실시간으로 공격을 탐지하는 능력을 측정하는 것입니다. 제가 근 (Near) 실시간이라고 말하는 이유는 모델 자체가 로그를 분석하고, 응답을 생성하여 우리에게 반환하는 데 항상 오버헤드(Overhead)가 발생하기 때문입니다.

왜 단순히 정규 표현식(Regex)과 시그니처만으로는 안 될까요?

전통적인 탐지 방식인 규칙 기반 WAF, 시그니처 기반 IDS, 정규 표현식(Regex) 필터 등은 설계된 목적에 충실합니다. 즉, 알려져 있고 텍스트로 명시적인 패턴을 포착하는 데 탁월합니다. ' OR '1'='1이 포함된 SQL 인젝션 (SQL Injection) 페이로드, ../../etc/passwd를 이용한 경로 탐색 (Path Traversal) 시도, <script>를 이용한 XSS 등은 모두 정적 패턴이 인식할 수 있는 명확한 "시그니처 (Signature)"를 가지고 있습니다.

문제는 공격의 한 부류 전체가 시그니처를 전혀 가지고 있지 않다는 점입니다. IDOR (Insecure Direct Object Reference, 부적절한 직접 객체 참조) / BOLA (Broken Object Level Authorization, 깨진 객체 수준 권한 부여)를 예로 들어보겠습니다:

GET /users/47b4f0a3-d582-47e9-832f-1e80ac12fe4b
Authorization: Bearer <common-user-token>

구문론적(Syntactically)으로 이 요청은 정상적인 요청과 동일합니다. 악성 문자도, 의심스러운 페이로드(payload)도 없습니다. 이것을 공격으로 만드는 것은 바로 **문맥(context)**입니다. 즉, 일반 사용자가 다른 사용자의 리소스에 접근하거나, 단일 토큰이 몇 초 사이에 수많은 서로 다른 ID를 건드리는 상황입니다. 정규 표현식(Regex)은 이를 알 방법이 없습니다. 정규 표현식은 한 줄의 문장을 볼 뿐, 그 이면의 이야기를 보지 못하기 때문입니다.

이 지점이 바로 AI가 게임의 판도를 바꾸는 곳입니다. LLM은 로그 세트의 문맥을 이해할 수 있습니다. IP를 상관 분석하고, 요청의 리듬(cadence)을 관찰하며, 최근에 생성된 토큰으로부터 온 PATCH /users/:id/promote-admin 요청이 개별적으로는 정상적으로 보일지라도 의미론적으로(semantically) 이상하다는 점을 포착할 수 있습니다. LLM은 단순히 형태(form)가 아니라, 행동으로부터 추론된 **의도(intent)**를 분석합니다.

범위: 본 프로젝트는 PoC입니다

처음부터 명확히 해두는 것이 중요합니다: **이 작업은 개념 증명(PoC, Proof of Concept)**입니다. 이는 운영 환경에 즉시 적용 가능한 제품도 아니며, 기업용 SIEM/WAF를 대체하는 것도 아닙니다. 이는 다음과 같은 타당성 질문에 답하기 위한 통제되고 재현 가능한 실험, 즉 하나의 "시작"입니다:

정적 도구(static tools)가 잡아내지 못하는 논리적/의미론적 공격을 포함하여, 경량 로컬 LLM을 사용하여 API 로그에서 실제 공격을 지목하는 것이 가능한가?

목표는 이 **접근 방식의 타당성(feasibility)**을 입증하고, 운영 시나리오를 향한 장단점 및 발전 경로를 그려보는 것입니다. 이 프로젝트는 운영 환경에 적합하지 않으며, 적절한 보호 메커니즘이 부족합니다.

3. 기술 스택

실험을 수행하기 위해 우리는 "전부 로컬(all local)" 정책을 채택할 것입니다. 로그 데이터는 기기를 떠나지 않으며, 제3자 API 호출도 없고, 추론(inference) 비용은 0입니다. 이는 로그에 민감한 데이터가 자주 포함되는 보안 분야에서 특히 중요합니다.

실행 플랫폼: Ollama

추론(Inference)은 http://localhost:11434에서 모델을 로컬로 노출하는 **Ollama**에서 실행됩니다. Ollama는 GPU에 모델을 로드하고, 컨텍스트(Context)를 관리하며, HTTP API를 통해 응답을 제공하는 역할을 수행합니다. 덕분에 어떤 Python 파이프라인에도 매우 쉽게 통합할 수 있습니다.

사용된 모델: qwen2.5-coder:1.5b

모델 선택은 의도적이었으며, 어쩌면 직관에 어긋날 수도 있습니다. 수백억 개의 파라미터를 가진 거대 모델 대신, 우리는 단 **1.5 billion parameters (15억 개 파라미터)**를 가진 **qwen2.5-coder:1.5b**를 선택했습니다. 그 이유는 다음과 같습니다:

  • 경량화 및 빠른 속도: 보다 겸손한 사양의 GPU VRAM에도 여유롭게 들어가며, 1분 단위의 분석 창(window) 내에서 충분히 빠르게 응답합니다.
  • 구조화된 작업에 최적화: coder 변형 모델로서, 구조화된 출력(JSON)을 이해하고 생성하며, 기술적 형식(HTTP, 경로, 쿼리 문자열)을 해석하고, 형식 지침을 따르는 데 특히 뛰어납니다. 이는 로그를 분류하는 데 정확히 필요한 특성입니다.
  • 효율성의 증명: 이번 실험 가설의 일부는 텍스트/구조화된 로그(text/structured logs) 분석에 거대한 모델이 필요하지 않다는 것입니다. 작고 특화된 모델만으로도 충분할 수 있습니다.

하드웨어 구성

실험은 전적으로 개발자 워크스테이션(서버가 아닌 소비자용 하드웨어)에서 수행되었습니다:

구성 요소사양
GPUNVIDIA RTX 3080 (10 GB VRAM)
...

언어 및 주요 라이브러리

생태계는 프로젝트의 실제 구조를 반영하여 두 영역으로 나뉩니다:

모니터 및 스크립트 (Python):

  • CrewAI — 분석 에이전트(Agent)의 오케스트레이션 (Agent, Task, Crew 정의).
  • langchain-ollama / Ollama 통합 — CrewAI와 로컬 모델 간의 가교 역할.
  • requests — API 로그 수집 및 트래픽/공격 스크립트 실행.
  • schedule — 분석 창(analysis windows) 스케줄링 (주기적 실행).
  • pydantic — 모델 출력의 검증(validation) 및 타이핑(typing).

대상 API (Node.js / TypeScript):

  • NestJS 11 — 사용자 관리 REST API를 위한 프레임워크 (framework). 분석할 대상이 필요하기 때문에 예시로 사용된 API입니다.
  • @nestjs/jwt + passport-jwt — JWT 인증 (authentication).
  • bcrypt — 비밀번호 해싱 (hashing).
  • class-validator / class-transformer — DTO 검증 (validation).
  • @nestjs/swagger — 자동 API 문서화 (documentation).

4. 아키텍처 및 프로젝트 구조

프로젝트는 네 가지 주요 블록으로 구성되었습니다: 대상 API (target API), 모니터 (LLM 에이전트, monitor (LLM agent)), 시뮬레이션/공격 스크립트 (simulation/attack scripts), 그리고 통합 유틸리티 (consolidation utilities). 일반적인 데이터 흐름은 다음과 같습니다:

┌─────────────────────┐     ┌──────────────────────┐     ┌─────────────────────┐
│  Simulation / Attack│────▶│   NestJS API         │────▶│  operations.log     │
│  (Python scripts)   │     │   (generates JSON    │     │  (api/logs/)        │
...

각 구성 요소의 거시적 역할

  • api/ — 대상 애플리케이션 (target application). JWT 인증을 사용하는 사용자 관리 API입니다. 실험에서의 핵심 역할은 logging/ 모듈에 있습니다. **전역 인터셉터 (global interceptor)**인 LoggingInterceptor가 각 요청을 캡처하여 구조화된 JSON 레코드(메서드, 경로, IP, userId, 정제된 바디(sanitized body), 상태 코드, 지연 시간(latency))를 기록합니다. GET /logs 엔드포인트를 통해 시간 범위 (time window) (?start=&end=&limit=)별로 이러한 레코드를 조회할 수 있으며, 이는 모니터가 소비하는 소스(source)가 됩니다.

  • monitor/ — AI 에이전트 (AI agent). main.py가 루프(loop) 내에서 실행됩니다. 매 분마다 시간 범위를 계산하고, GET /logs를 통해 로그를 가져오며, 프롬프트(prompt)를 조립한 뒤 CrewAI의 Crew를 실행합니다. 모델의 응답은 Pydantic 스키마(schema)를 통해 검증된 후 analysis-YYYYMMDD-HHMMSS.json 파일로 저장됩니다.

  • scripts/trafic-simulation/ — **정상적인 배경 소음 (legitimate background noise)**을 생성합니다: 회원가입, 올바른 로그인 및 잘못된 로그인, 프로필 수정, 비밀번호 재설정, 예상되는 검증 오류 (400/401/409).

이는 모델이 정상적인 트래픽과 공격을 구분하는지(단순히 모든 것에 대해 "공격"이라고 외치는 것이 아닌지) 테스트하는 데 있어 매우 중요합니다.

  • scripts/attacks/제어된 공격 (controlled attacks): 패스워드 스프레이 (password spray), 사용자 열거 (user enumeration), 그리고 IDOR. 모든 공격은 로컬 API를 대상으로만 실행됩니다.

  • scripts/utils/aggregate_results.py — 모든 결과 JSON 파일을 집계된 지표(metrics)가 포함된 Markdown 보고서로 통합합니다 (섹션 7의 기초가 됩니다).

5. 에이전트 설정 및 동작 (Agent Configuration and Behavior)

에이전트는 페르소나 (persona, 에이전트가 누구인지)와 태스크 (task, 에이전트가 무엇을 해야 하는지)를 깔끔하게 분리하는 CrewAI를 사용하여 모델링되었습니다. 실험의 모든 "지능"은 설정 파일의 프롬프트 엔지니어링 (prompt engineering)에 담겨 있습니다.

페르소나: 시니어 보안 분석가

config/agents.yml 파일에서 security_log_analyst 에이전트는 역할 (role), 목표 (goal), 그리고 상세한 배경 이야기 (backstory)를 부여받습니다:

  • 역할 (Role): "애플리케이션 및 API 로그에서 취약점과 이상 동작을 탐지하는 데 특화된 시니어 사이버 보안 분석가 (Senior cybersecurity analyst)."
  • 목표 (Goal): OWASP API Security Top 10 (2023) 표준에 따라 API 실행 로그를 분석하여 활성 공격을 탐지하고 우선순위를 지정하며, 트리거된 기준, 정확한 증거, 심각도 (severity), 신뢰도 점수 (confidence score, 0–100), 그리고 권장 조치를 포함한 간결한 조사 결과를 생성합니다.

진정한 핵심은 분석가의 "두뇌" 역할을 하는 **배경 이야기 (backstory)**에 있습니다. 이는 모델에게 각 로그 이벤트 — HTTP 메서드 (HTTP method), 경로 (path), 쿼리 문자열 (query string), 헤더 (headers), 바디 (body), 상태 코드 (status code), 지연 시간 (latency), 소스 IP (source IP), 사용자 에이전트 (user-agent), 토큰 신원 (token identity), 그리고 시간적 상관관계 (temporal correlation) — 를 검사하고, 각각 명시적인 매칭 (match) 규칙이 있는 10가지 OWASP API Top 10 기준에 따라 분류하도록 지시합니다. 프롬프트에 포함된 몇 가지 예시는 다음과 같습니다:

  • [Detect:API1-BOLA] — 경로 내의 순차적 ID/외부 UUID, 짧은 간격 내에 많은 서로 다른 ID에 접근하는 동일 토큰, ID 스왑 (ID swap) 시 200 응답 반환 → IDOR (Insecure Direct Object Reference).
  • [Detect:API2-BrokenAuth] — 401/403 오류의 급증, 크리덴셜 스터핑 (credential stuffing)/무차별 대입 공격 (brute force), 속도 제한 (rate limiting) 없는 login/token/reset-password에 대한 대량 요청.
  • [Detect:API5-BFLA] — 권한이 낮은 토큰에 의한 권한 있는 경로 (/admin, /users/:id/role) 호출; 수평적/수직적 권한 상승 (escalation).
  • ...그리고 API10-UnsafeConsumption (전형적인 인젝션: SQLi, NoSQLi, XSS, 커맨드 인젝션 (Command Injection), 경로 탐색 (Path Traversal))까지 계속됩니다.

다음 세 가지 행동 지침이 특히 중요합니다:

  1. 오탐 (False positive) 감소: 프롬프트는 모델이 무언가를 공격으로 분류하기 전에 _빈도, 반복성, 공유된 기원, 그리고 해당 경로의 예상 기준선 (baseline)으로부터의 이탈을 상관 분석 (correlate)_하도록 지시하며, 기준을 충족하지 않을 경우 [Benign] (정상)으로 표시하도록 합니다.
  2. 분석가 자체의 안전: "악성 페이로드 (malicious payloads)를 능동적으로 실행, 재현 또는 에코(echo)하지 마십시오 — 오직 증거로서만 참조하십시오." — 에이전트는 페이로드를 능동적으로 재현하지 않고 오직 증거로만 인용합니다.
  3. 상관관계 (Correlation): 분산형/상관관계가 있는 공격의 경우, IP/토큰/시간 창 (time window)별로 집계하고 심각도 (severity)를 높입니다.

구조화된 출력

작업(tasks-analise-logs-owasp.yml)은 모델이 엄격한 JSON을 반환하도록 요구하며, 이는 models/analyze_result.py에 있는 Pydantic 스키마에 의해 검증됩니다:

class Context(BaseModel):
    method: str
    path: str
...

다시 말해: 에이전트는 로그 배치를 읽고, 이상 징후에 대해 추론하며, 의심스러운 이벤트 (suspicious events) 목록을 반환합니다. 각 이벤트에는 증거, 심각도, 신뢰도 (confidence, 0–100%), 권장 조치, 그리고 전체 HTTP 컨텍스트 (context)가 포함됩니다. 이러한 구조화 덕분에 결과를 객관적으로 집계하고 측정할 수 있습니다.

AI 자동 생성 콘텐츠

본 콘텐츠는 Dev.to AI tag의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.

원문 바로가기
0

댓글

0