웹 취약점 진단을 자동화하는 멀티 에이전트 아키텍처, 38종 액티브 스캐너 체크, 55개 MCP 도구의 설계 노트.

TL;DR

  • 단일 LLM이 아니라 **Planner(전략) · Worker(실행) · Parser(판정)**로 역할을 쪼갠 멀티 에이전트 구조.
  • LLM 프롬프트에 의존하지 않고 코드 레벨 가드 7종으로 무한 루프·중복 보고·조기 종료를 강제 차단.
  • PTT(Pentesting Task Tree) 로 모든 엔드포인트 × 취약점 조합의 상태를 추적해 커버리지/종료 조건을 명확화.
  • Reflection vs Execution 구분, OOB(Interactsh) 콜백, 3계층 FP 방어로 자동 스캐너 특유의 오탐을 줄임.
  • AWS Bedrock 기반 11종 모델 지원, tool_use 미지원 모델도 text-mode fallback으로 수용.

1. 왜 만들었나

웹 애플리케이션 보안 진단은 숙련된 전문가가 Burp Suite 같은 도구를 들고 수행한다. 문제는 세 가지였다.

  1. 전문가 의존성 — 진단 품질이 사람에 따라 들쭉날쭉하다.
  2. 반복 작업의 비효율 — 매번 비슷한 패턴의 취약점을 수동으로 확인한다.
  3. 커버리지 한계 — 시간 제약 때문에 모든 엔드포인트를 테스트하기 어렵다.

LLM이 코드를 이해하고, HTTP를 주고받고, 결과를 판정할 수 있다면 — 이 과정을 자동화할 수 있지 않을까? 거기서 출발했다.

단순한 “GPT에게 물어보기"가 아니다. 실제 HTTP 요청을 보내고, 응답을 분석하고, 전략을 수정하고, 구조화된 보고서를 생성하는 자율 에이전트 시스템이다.


2. 시스템 아키텍처 개요

┌─────────────────────────────────────────────────────────┐
│                     Web Platform (UI)                    │
│  Dashboard / Targets / Sessions / Findings / Reports     │
└─────────────────────┬───────────────────────────────────┘
                      │ REST API
┌─────────────────────▼───────────────────────────────────┐
│                  FastAPI Backend                         │
│  ┌──────────┐  ┌──────────┐  ┌──────────┐               │
│  │  Target  │  │ Finding  │  │  User /  │               │
│  │  Manager │  │ Workflow │  │   RBAC   │               │
│  └──────────┘  └──────────┘  └──────────┘               │
└─────────────────────┬───────────────────────────────────┘
                      │
┌─────────────────────▼───────────────────────────────────┐
│              Multi-Agent Engine                          │
│                                                          │
│  ┌──────────┐    ┌──────────┐    ┌──────────┐           │
│  │ Planner  │───▶│  Worker  │───▶│  Parser  │           │
│  │ (전략가) │    │ (실행자) │    │ (판정자) │           │
│  └──────────┘    └──────────┘    └──────────┘           │
│       │               │                                  │
│       ▼               ▼                                  │
│  ┌──────────┐    ┌──────────┐                           │
│  │   PTT    │    │ 55 MCP   │                           │
│  │ Task Tree│    │  Tools   │                           │
│  └──────────┘    └──────────┘                           │
│                                                          │
│  ┌──────────────────────────────────────────┐           │
│  │         38종 Active Scanner Checks       │           │
│  └──────────────────────────────────────────┘           │
└─────────────────────┬───────────────────────────────────┘
                      │
          ┌───────────┼───────────┐
          ▼           ▼           ▼
     PostgreSQL   Interactsh   AWS Bedrock
       (DB)      (OOB Server)   (LLM API)

3. 핵심 설계: Planner / Worker / Parser

처음에는 단일 LLM이 모든 것을 하는 구조로 시작했다. 문제가 바로 터졌다.

  • Conversation history가 길어지면 LLM이 이전 맥락을 잊는다.
  • 전략 수립과 페이로드 생성을 동시에 시키면 둘 다 품질이 떨어진다.
  • 결과 판정에서 False Positive가 대량 발생한다.

해결책은 역할 분리였다.

3.1 Planner — “무엇을 테스트할까”

Planner는 Conversation History 없이 동작한다. 매 턴마다 External State Store의 스냅샷만 받는다.

{
  "phase": "unauth_test",
  "endpoints": ["http://target/login", "http://target/api/users"],
  "ptt_actionable": [
    {"endpoint": "/login", "vuln_type": "sqli", "status": "todo"},
    {"endpoint": "/api/users", "vuln_type": "idor", "status": "candidate"}
  ],
  "needs_report": [
    {"endpoint": "/login", "vuln_type": "sqli", "evidence": "SQL error in response"}
  ],
  "already_reported": ["sqli@/login"],
  "already_tested": ["xss@/login"],
  "confirmed_vulns": ["cmdi@/tools/ping"]
}

이 구조의 장점:

  • 무한 루프 방지 — 이미 테스트한 항목이 명시돼 있어 반복 불가.
  • 중복 보고 방지 — already_reported 목록을 코드 레벨에서 가드.
  • Phase 전환 — recon → unauth_test → auth_test → deep_test → wrap_up 자동 진행.

Planner의 출력은 단일 JSON 액션이다.

{
  "last_step_analysis": "이전 단계에서 /login에 SQLi가 확인됨. 보고 후 다음 엔드포인트로 이동",
  "action": "report_finding",
  "params": {
    "title": "SQL Injection in Login",
    "finding_type": "sqli",
    "severity": "critical"
  }
}

3.2 Worker — “어떻게 테스트할까”

Worker는 실제 HTTP 요청을 보내는 에이전트다. Planner가 “이 엔드포인트의 SQLi를 테스트하라"고 지시하면, Worker가 페이로드를 생성하고, 요청을 보내고, 응답을 분석한다.

Worker Loop (최대 N회 시도):
  1. 페이로드 생성 → repeater_send 도구 호출
  2. 응답 수신 → Parser가 판정
  3. 취약점 미확인 → 다른 접근법으로 재시도
  4. 취약점 확인 or 시도 소진 → 결과 반환

핵심 설계 결정: Worker는 tool_use API를 사용한다. LLM이 직접 도구를 호출한다.

Worker:  "repeater_send로 SQLi 페이로드를 보내겠다"
→ tool_use: repeater_send({url: "http://target/login", method: "POST",
                            body: "user=' OR 1=1--"})
→ 결과:   {status: 200, body: "sqlite3.OperationalError: near ..."}
→ Worker: "SQL 에러 확인. UNION 기반 데이터 추출 시도"
→ tool_use: repeater_send({...})

tool_use 미지원 모델 대응 (Text Fallback)

DeepSeek R1 같은 모델은 Bedrock Converse API의 tool_use를 지원하지 않는다. 그래서 text-mode fallback을 구현했다.

  • 시스템 프롬프트에 도구 설명을 텍스트로 포함.
  • 모델이 JSON 텍스트로 도구 호출을 출력: {"tool": "repeater_send", "input": {...}}
  • 응답에서 JSON 파싱 → 도구 실행 → 결과를 다음 메시지로 피드백.
  • <think> 태그(reasoning 모델 출력) 자동 제거.
NO_TOOL_USE_MODELS = {"us.deepseek.r1-v1:0"}

async def work(self, ...):
    if not supports_tool_use(self.worker_model):
        return await self._work_text_mode(...)   # Text fallback
    return await self._work_tool_use(...)        # Native tool_use

3.3 Parser — “결과가 맞나”

Parser는 Worker의 결과를 판정한다. 2단계로 동작한다.

1단계: Rule-based (코드)

_VULN_KEYWORDS = {
    "cmdi": ["uid=", "root:", "/bin/bash"],
    "sqli": ["syntax error", "mysql_", "operationalerror"],
    "ssti": ["${", "{##"],
    # ...
}
  • 도구별 응답 파싱 (repeater_send, scanner_active_scan 등).
  • HTML 태그 제거 후 clean text에서 키워드 매칭.
  • 자동 확정 로직: uid=\d+\( → cmdi 확정, operationalerror → sqli 확정.

2단계: LLM Parser (애매한 경우만)

Rule-based에서 _needs_llm=True가 반환되면 Parser LLM이 판단한다. 비용 절감을 위해 대부분은 1단계에서 결정된다.


4. PTT (Pentesting Task Tree)

모든 테스트 상태를 추적하는 자료구조다.

PTT Structure:
  endpoint → vuln_type → TaskNode

Example:
  /login
    ├── sqli: {status: "verified", attempts: 3, last_result: "SQL error confirmed"}
    ├── xss:  {status: "not_vuln", attempts: 2}
    └── cmdi: {status: "todo", attempts: 0}
  /api/users
    ├── idor: {status: "candidate", attempts: 0}
    └── sqli: {status: "todo", attempts: 0}

TaskNode 상태 전이:

todo → (Worker 테스트) → verified / not_vuln
candidate → todo (Planner 승격)
verified → reported (보고 완료)

PTT가 해결하는 문제:

  • 커버리지 추적 — 어떤 엔드포인트의 어떤 취약점이 미테스트인지.
  • 중복 방지 — 같은 테스트를 반복하지 않음.
  • 종료 판단 — 모든 노드가 verified/not_vuln/reported면 진단 완료.

5. 코드 레벨 가드 — 프롬프트가 아닌 코드로

LLM 기반 시스템에서 가장 큰 위험은 프롬프트 의존성이다. “중복 보고하지 마시오"라고 프롬프트에 써도 LLM은 무시할 수 있다. 모든 핵심 제약은 코드로 강제한다.

문제 코드 가드
같은 취약점 중복 보고 report_finding 호출 시 PTT에서 reported 여부 확인 → 거부
이미 테스트한 항목 재테스트 PTT status가 verified/not_vuln이면 Worker 호출 스킵
무한 루프 (같은 액션 반복) planner_dispatches 카운터 → 3회 초과 시 강제 not_vuln
연속 스킵 루프 consecutive_skips → 5회 연속이면 남은 PTT 전부 not_vuln
연속 중복 차단 consecutive_dup_blocks → 5회 연속이면 남은 노드 전부 reported
agent_done 조기 호출 PTT에 todo가 남아 있으면 거부
비용 초과 max_cost_usd 체크 → 초과 시 강제 종료 + 보고서 생성

6. 스캔 깊이 프로파일

세 가지 깊이로 진단 범위를 조절한다.

Quick Normal Thorough
Spider 크롤링 2레벨 / 50페이지 3레벨 / 100페이지 5레벨 / 200페이지
Worker 시도 횟수 2회 5회 8회
Scanner 체크 11종 (고위험) 38종 전체 38종 전체 + 추가 분석
Planner 전략 고위험 집중, 빠른 진행 체계적 전수 검사 모든 파라미터·엔드포인트, OOB/blind, WAF 우회

Quick 모드가 돌리는 11종:

sqli, xss, cmdi, ssti, path_traversal, ssrf,
info_disclosure, auth_bypass, backup_disclosure,
security_headers, default_creds

7. 38종 Active Scanner 체크

기본 (17종)

체크 탐지 기법
SQL Injection Error-based + Boolean blind + Time-based
XSS Reflection 탐지 (인코딩 구분)
OS Command Injection Canary 실행 확인 (반영 vs 실행 구분)
SSTI 수식 평가 확인 (49 vs {{7*7}})
XXE External Entity 파싱 + OOB
Deserialization Pickle / YAML / PHP 직렬화
Path Traversal 다중 인코딩 변형
Open Redirect 외부 도메인 리다이렉트
SSRF 내부 IP / 메타데이터 접근
CORS Misconfiguration 임의 Origin 허용 + credentials
Host Header Injection 비밀번호 재설정 링크 조작
Web Cache Poisoning Unkeyed 헤더 캐시 반영
WebSocket Hijacking Origin 검증 + CSWSH
CSRF 토큰 검증 누락
Header Injection HTTP 응답 헤더 주입
Info Disclosure 디버그 엔드포인트 / 스택 트레이스
Auth Bypass 인증 없이 보호된 리소스 접근

확장 (9종)

체크 탐지 기법
NoSQL Injection MongoDB $gt/$ne/$regex 연산자
LDAP Injection 필터 주입 ()(cn=*))
SSI Injection <!--#exec--> 디렉티브
Log4Shell JNDI 페이로드 + OOB (난독화 3종)
Prototype Pollution __proto__/constructor.prototype + 영속성
Mass Assignment 권한 필드 12종 주입
File Upload PHP/JSP/HTML/SVG + 이중 확장자·null byte
Clickjacking X-Frame-Options + CSP frame-ancestors
Email Header Injection CRLF Bcc 주입

인프라 / 구성 (12종)

체크 탐지 기법
Security Headers HSTS/CSP/CORP/COOP 등 8종 + 약한 값
Cookie Security Secure / HttpOnly / SameSite 플래그
HTTP Methods TRACE(XST) / PUT / DELETE / WebDAV
CRLF Injection 응답 헤더 주입 4종 변형
Backup Disclosure .git / .env / .bak 등 38경로
Directory Listing Apache / Nginx / IIS 인덱싱
Default Credentials 18종 기본 계정 + 폼 자동 발견
Cloud Metadata SSRF AWS / Azure / GCP / DO / Oracle / Alibaba 7종
HTTP Parameter Pollution 중복 파라미터 동작 탐지
Account Enumeration 응답 차이 / 타이밍 분석
Session Fixation 로그인 전후 세션 ID 변경
Blind XSS OOB JS 페이로드 + 지연 콜백

Reflection vs Execution 구분

FP 방지의 핵심이다.

cmdi: echo bla7cmdi42 전송
  → 응답에 "bla7cmdi42" + "echo" 둘 다 있음 → 반영(XSS), NOT cmdi
  → 응답에 "uid=1000(user)" 있음         → 실행(cmdi) ✓

ssti: {{7*7}} 전송
  → 응답에 "49" + "{{7*7}}" 둘 다 있음 → 반영, NOT ssti
  → 응답에 "49"만 있고 "{{7*7}}" 없음  → 실행(ssti) ✓

8. 55개 MCP 도구

에이전트가 사용하는 도구 체계다.

핵심 도구

카테고리 도구 설명
HTTP repeater_send 요청 전송 (raw + url 모드)
HTTP http_raw_request Raw 소켓 레벨 요청
HTTP http_send_concurrent Race condition 테스트
크롤링 spider_crawl / spider_get_sitemap 웹 크롤링 + 사이트맵
스캐너 scanner_passive_scan / scanner_active_scan 자동 스캔
인증 auth_login / extract_tokens 로그인 + 토큰 추출
분석 diff_requests / response_search 응답 비교·검색
퍼징 fuzz_wordlist / intruder_attack 경로·파라미터 퍼징

보안 분석 도구

도구 설명
jwt_analyze / jwt_forge / jwt_crack JWT 분석, 변조, 시크릿 크래킹
graphql_introspect / graphql_query / graphql_test GraphQL 스키마 추출 + 보안 테스트
oauth_analyze OAuth 리다이렉트 우회 + state 파라미터
oob_generate / oob_check OOB 콜백 (Interactsh)
websocket_connect WebSocket + CSWSH 테스트
subdomain_check / subdomain_check_bulk 서브도메인 탈취

정보 수집 도구

도구 설명
js_analysis JS에서 API 엔드포인트·시크릿·DOM XSS 싱크 추출
wappalyzer 기술 스택 탐지 (50+ 시그니처)
param_miner 숨겨진 파라미터·헤더 60+종 브루트포스
dns_lookup / cert_check DNS 조회 + TLS 인증서 분석
cookie_analyzer 쿠키 보안 속성 종합 분석
security_headers 보안 헤더 등급 (A–F)
backup_finder 60+ 민감 파일 경로 스캔
api_schema_import OpenAPI / Swagger 자동 발견 + 파싱

보고 / 기록

도구 설명
report_finding 구조화된 취약점 보고 (DB 저장)
take_note 메모 기록 (보고서 부록)
check_waf WAF 탐지 + 차단 페이로드 식별
encoding_helper 12종 인코딩 체인 (WAF 우회)

9. False Positive 최소화 전략

FP는 자동화 보안 도구의 가장 큰 약점이다. 세 겹으로 방어한다.

계층 1 — Scanner 레벨

  • Reflection vs Execution 구분 (canary가 반영만 되면 XSS, 실행되면 해당 취약점).
  • Content-Type 프로빙 (XXE / Deserialization은 해당 타입을 수용하는 엔드포인트만).
  • Fingerprint 매칭 (backup_disclosure는 파일 내용 패턴 확인).

계층 2 — Parser 레벨 (Rule-based)

  • _VULN_KEYWORDS 엄격 매칭 — 실제 에러 시그니처만(generic 문자열 제외).
  • _confirmed 자동 탐지 — uid=\d+\( 패턴이면 cmdi 확정.
  • HTML 태그 제거 후 clean text 분석 — 페이지 설명 텍스트에서의 오탐 방지.

계층 3 — Planner 레벨 (FP 필터링)

report_finding 호출 전 5가지 필수 확인:

  1. 파라미터 실존 — Spider/form에서 발견된 파라미터인가?
  2. Injection 실행 확인 — 반영이 아닌 실행인가?
  3. 엔드포인트 실존 — 404가 아닌가?
  4. 중복 보고 방지 — 이미 보고된 항목이 아닌가?
  5. 증거 강도 — “가능성"이 아닌 “확인"인가?

10. 보고서 생성

보고서는 코드 스켈레톤 + LLM 내러티브 하이브리드 방식이다.

코드가 생성하는 부분 (모델 무관, 항상 동일)

  • 메타 정보 테이블 (대상, 세션 ID, 일시).
  • 모델별 / 역할별 토큰 사용량 + 비용.
  • 취약점 현황 (심각도별 건수).
  • 카테고리별 그룹핑 + 메타데이터 테이블 (CVSS, CWE, OWASP).
  • 발생 위치 테이블 + 상세 증거.
  • 공격 체이닝 시나리오 (코드 레벨 폴백).

LLM이 생성하는 부분 (모델 품질에 따라 다름)

  • 종합 평가 (Executive Summary).
  • 취약점별 영향도 분석.
  • 공격 체이닝 시나리오 (LLM 분석).
  • 우선순위별 권고 사항.

공격 체이닝 자동 생성

LLM 분석이 실패해도 코드 레벨 폴백으로 항상 체이닝 시나리오가 생성된다.

_chain_templates = [
    {
        "requires": [("sql injection",),
                     ("information disclosure", "backup", "sensitive file")],
        "title": "SQL Injection → 데이터 탈취 → 관리자 권한 획득",
        "steps": [
            "SQL Injection으로 사용자 테이블 덤프",
            "관리자 비밀번호 해시 추출",
            "해시 크래킹 → 관리자 로그인",
            "시스템 전체 데이터 접근",
        ],
    },
    # ... 8종 체이닝 템플릿
]

발견된 취약점 조합에 매칭되는 템플릿이 자동 선택된다.


11. 멀티 모델 지원

AWS Bedrock을 통해 11종 모델을 지원한다. 역할별로 다른 모델을 배치할 수 있다.

역할 권장 모델 이유
Planner Claude Opus 4.6 전략적 판단, 보안 컨텍스트 차단 없음
Worker Claude Sonnet 4.6 / DeepSeek V3.2 빠른 도구 호출, 비용 효율
Parser Claude Sonnet 4.6 간단한 판정, 저비용

.env로 모델 번호를 설정한다.

BLASUITE_PLANNER_MODEL=1   # Claude Opus 4.6
BLASUITE_WORKER_MODEL=3    # Claude Sonnet 4.6
BLASUITE_PARSER_MODEL=3    # Claude Sonnet 4.6

모델 호환성 현실

보안 테스트 컨텍스트에서 모든 모델이 작동하진 않는다.

  • Claude Opus 4.6 — 유일하게 Planner로 안정 작동.
  • GPT 계열 — cyber_policy 차단으로 공격 페이로드 생성 불가.
  • DeepSeek R1 — tool_use 미지원이지만 text fallback으로 Worker 사용 가능.
  • DeepSeek V3.2 — 일반 chat 모델, tool_use 지원, Worker에 적합.

12. 웹 플랫폼과 Finding 워크플로우

단일 HTML SPA로 구현된 웹 플랫폼.

Dashboard → Targets → Sessions → Findings → Reports

Finding 생명주기

found → reported → fixing → fixed → verified / inadequate
                                          ↓
                                     (이행점검 재실행)
  • RBAC: admin / auditor / developer / viewer.
  • 이행점검(Verification): 이전 세션의 confirmed_payload로 재테스트.
  • 카테고리별 이행점검: 특정 취약점 유형만 선택 검증.

13. OOB (Out-of-Band) 탐지

Blind 취약점은 응답에 증거가 없다. OOB 서버(Interactsh)로 콜백을 받아 탐지한다.

1. oob_generate → interaction_id + DNS/HTTP URL 생성
2. Worker가 페이로드에 OOB URL 삽입:
   - SSRF:      fetch('http://{oob_url}')
   - CMDi:      curl http://{oob_url}
   - XXE:       <!ENTITY xxe SYSTEM "http://{oob_url}">
   - Log4Shell: ${jndi:ldap://{oob_dns}/a}
3. 대기 후 oob_check → callback_received=true면 확인

Docker Compose로 Interactsh를 함께 배포한다.


14. Docker 배포

services:
  app:
    build: .
    ports: ["8000:8000"]
    environment:
      DATABASE_URL: postgresql+psycopg2://user:pass@db/blasuite
      BLASUITE_PLANNER_MODEL: "1"
      BLASUITE_WORKER_MODEL: "3"
    volumes:
      - ${HOME}/.aws:/root/.aws   # AWS 자격증명

  db:
    image: postgres:16

  oob:
    image: projectdiscovery/interactsh-server
    command: ["-skip-acme", "-d", "oob.example.com"]
    ports: ["10053:53/udp", "10080:80"]

15. 설계 과정에서 배운 것

프롬프트에 의존하지 마라

“중복 보고하지 마시오"를 프롬프트에 아무리 써도 LLM은 무시한다. 모든 핵심 제약은 코드 가드로 강제해야 한다. 프롬프트는 가이드라인, 코드는 법률.

Conversation History를 없애라

처음에는 Planner에게 전체 대화 이력을 넘겼다. 50턴이 넘어가면 초반 맥락을 잊고 같은 작업을 반복했다. External State Store로 전환한 후 — 매 턴 JSON 스냅샷만 제공 — 무한 루프가 사라졌다.

과최적화를 경계하라

테스트 앱 하나에 맞춰 최적화하면 실전에서 무용지물이다. 특정 URL 패턴·파라미터명에 대한 하드코딩은 절대 금지. 모든 로직은 제네릭해야 한다.

Reflection ≠ Execution

자동 스캐너 FP 대부분은 이 구분 실패에서 온다. echo bla7cmdi42를 보냈는데 응답에 bla7cmdi42가 있으면 — 그건 XSS(반영)이지 CMDi(실행)가 아니다. uid=1000(user)가 있어야 실행이다.

비용 관리는 필수다

LLM 기반 시스템은 비용이 예측 불가능하다. Per-model / per-role 토큰 트래킹 + session-level 비용 한도가 없으면, thorough 모드 한 번에 수십 달러가 나갈 수 있다.


16. 현재 상태와 로드맵

구현 완료

  • 38종 Active Scanner 체크
  • 55개 MCP 도구
  • 11종 LLM 모델 지원 (text fallback 포함)
  • Planner / Worker / Parser 멀티 에이전트
  • PTT 기반 상태 추적
  • 코드 레벨 가드 7종
  • 웹 플랫폼 (RBAC, Finding 워크플로우, 이행점검)
  • Docker Compose 배포
  • OOB 탐지 (Interactsh)
  • 한국어 보고서 + 공격 체이닝

남은 과제

  • Stored XSS 탐지 — 크롤 + 저장 + 재방문 인프라.
  • HTTP Request Smuggling — raw socket CL.TE / TE.CL.
  • Playwright 기반 DOM 테스트 — 실제 브라우저 렌더링.
  • PDF 보고서 — 실무 납품용.
  • Jira / Slack 연동 — Finding → 이슈 자동 생성.
  • CI/CD 통합 — GitHub Actions / GitLab CI 파이프라인.
  • 멀티모델 벤치마크 — 동일 타겟 대상 모델별 성능 비교.

이 시스템은 인가된 모의해킹 환경에서만 사용해야 한다. 무단으로 타인의 시스템을 진단하는 행위는 법적 문제를 야기한다.