> 대상 프로젝트의 소스코드를 공격자 관점에서 분석하여 > 시나리오 기반 취약점 탐색, POC 생성, 선택적 라이브 검증을 수행합니다. ---
Scanned 5/28/2026
Install via CLI
openskills install ch015/code-pentester# 모의해킹 (Penetration Testing) Skill
> 대상 프로젝트의 소스코드를 공격자 관점에서 분석하여
> 시나리오 기반 취약점 탐색, POC 생성, 선택적 라이브 검증을 수행합니다.
---
## 서비스 개요
| 항목 | 내용 |
|------|------|
| 서비스명 | 모의해킹 (Pentest) |
| 방법론 | 시나리오 기반 공격 + 방법론 기반 분석 |
| 출력물 | 취약점 상세 + 6-step 영향도 분석 + POC 코드 + 라이브 검증 결과 |
| 코드 수정 | ❌ 없음 (읽기 전용) |
---
## 설계 원칙: 방법론 기반 + 공격자 사고
### 분석 원칙: 방법론, 패턴이 아님
```yaml
Principles:
No_Pattern_Lists: |
"특정 프레임워크 구문, grep 패턴, 시크릿 접두사 목록에 의존하지 않는다.
이런 목록은 닫힌 집합이며, 목록에 없는 위험을 구조적으로 놓친다."
Use_Methodology: |
"행위(무엇이 일어나는가)를 질문하고, AI가 감지된 기술 스택에 맞는
구체적 코드 패턴을 자율적으로 판단하여 탐색한다."
Attacker_Mindset: |
"방어자가 아닌 공격자 관점으로 코드를 읽는다.
'이 기능이 안전한가'가 아니라 '이 기능을 어떻게 악용할 수 있는가'를 질문한다."
Representative_Examples: |
"안티패턴/올바른 패턴은 '대표적 예시'로만 제시.
분석은 이 예시에 한정되지 않으며 — 동일한 구조적 이슈를 가진
모든 변형이 탐지되어야 한다."
```
---
## Phase 구조
```
Phase 0: Recon → 공통 정찰 (common/recon.md 참조)
Phase 0.5: Binding → 정찰 → 분석 컨텍스트 바인딩
Phase 1: Architecture → 8대 아키텍처 차원 리뷰 + 공격 확장 (M9, M10)
Phase 2: Deep Analysis → 원칙 기반 심층 분석 + 공격 체인
Phase 3: Attack → 공격 카테고리 시나리오 분석
Phase 3.5: Creative → 체크리스트 외 프로젝트 고유 공격 추론
Phase 4: POC → 검증 가능한 POC 코드 생성
Phase 4.5: Self-Verify → 분석 결과 자체 검증 (도달 가능성, 보상 제어, 전제조건 분석, 로컬 PoC)
Phase 5: Report → 종합 보고서 + 6-step 영향도 분석 + 전제조건 포괄 그룹
Phase 5R: Regulatory → 규제 영향 참조 (Finding 기반, 해당 시에만)
Phase 6.0: Sweep → 엔드포인트 전수 기본 테스트 (--url 옵션 시, Finding 무관)
Phase 6: Live → Finding 기반 라이브 검증 (--url 옵션 시)
```
---
## Phase 1: 아키텍처 차원 리뷰 + 공격 확장
### 모듈 로딩
Pentest Phase 1은 VA의 A1-A8 아키텍처 차원 분석을 기반으로 합니다. 다음 모듈을 로드합니다:
```yaml
Required_Modules:
VA_Dimensions: "offsec/va/SKILL.md → Phase 1~3 (A1-A8 아키텍처 차원 정의)"
Compliance: "offsec/va/compliance.md → OWASP/Secure Coding/NIST 매핑 기준"
Compensating_Control: "common/compensating-control.md → 보상 제어 4단계 검증"
Deep_Analysis: "offsec/va/deep-analysis.md → 원칙 기반 심층 분석"
```
VA의 A1-A8 아키텍처 차원 리뷰를 수행하되, **공격자 관점**에서 다음을 추가로 추적합니다:
- **강도**: 각 보안 메커니즘의 강도 (강/중/약)
- **우회 가능성**: 공격자가 메커니즘을 우회할 수 있는 경로
### 공격 확장 차원
VA의 A1-A8에 더해 **M9 비즈니스 플로우 무결성**과 **M10 정보 노출 통제**를 추가로 추적합니다.
### M9. 비즈니스 플로우 무결성 (Business Flow Integrity)
소스코드에서 비즈니스 플로우를 추적하여 **설계 수준의 논리적 결함**을 식별합니다.
```yaml
Review_Perspectives:
Multi_Step_Flow:
question: "비즈니스 플로우의 단계를 스킵할 수 있는가?"
methodology: |
1. 비즈니스 플로우 식별: 생성→실행→정산, 신청→결제→확정
2. 각 단계별 독립 API 엔드포인트 식별
3. 중간 단계 스킵 가능성 분석
4. 단계 간 상태 검증 존재 여부
Entity_Lifecycle_Abuse:
question: "비활성/만료된 엔티티로 핵심 기능을 수행할 수 있는가?"
methodology: |
1. 소프트 삭제 엔티티로 핵심 기능 수행 가능 여부
2. 만료된 API 키, 세션, 초대링크로 작업 수행 가능 여부
3. 각 API에서 is_active/status 검증 일관성
Competition_Logic:
question: "경쟁/매칭 로직에 결함이 있는가?"
methodology: |
1. 자기 리소스끼리 대결/경쟁 가능 여부
2. 타인 리소스를 지정하여 이벤트 참가 가능 여부
3. 상태/진행/점수 직접 변경 가능 여부
4. 유료 리소스에 무료 엔드포인트로 접근 가능 여부
Admin_Access_Control:
question: "관리자 기능에 대한 접근 제어가 일관적인가?"
methodology: |
1. URL 직접 접근으로 관리자 페이지 로드 가능 여부
2. 관리자 API에 네트워크 레벨 보호 존재 여부
3. 관리자 미들웨어의 일관적 적용
Representative_Anti_Patterns:
- "비즈니스 플로우 중간 단계 스킵으로 결제 없이 서비스 사용"
- "소프트 삭제 엔티티가 여전히 핵심 기능에서 유효"
- "자기 리소스끼리 매칭하여 보상 획득"
Representative_Healthy_Patterns:
- "각 단계에서 이전 단계 완료 상태 서버 측 검증"
- "모든 API에서 엔티티 활성 상태 일관되게 체크"
- "관리자 기능 서버 미들웨어 + 네트워크 레벨 이중 보호"
```
### M10. 정보 노출 통제 (Information Disclosure Control)
```yaml
Review_Perspectives:
API_Response_Data:
question: "API 응답에 불필요한 데이터가 포함되는가?"
methodology: |
1. SELECT * 또는 과도한 컬럼 조회 패턴
2. 관계 JOIN 시 불필요 필드 노출
3. 리더보드/참가자 목록에서 불필요 사용자 정보
Business_Sensitive:
question: "비즈니스 민감 정보가 외부에 노출되는가?"
methodology: |
1. 리소스 내부 설정(system_prompt, config) 타인에게 노출
2. 보상 배분/알고리즘/수수료 정보 노출
3. 서버 버전, 프레임워크 정보 헤더 노출
PII_Exposure:
question: "개인식별정보가 불필요하게 노출되는가?"
methodology: |
1. 공개 API에 이메일, 전화번호, 실명 포함 여부
2. JWT 토큰 payload에 PII 포함
3. 에러 응답에 사용자 식별 정보 포함
Representative_Anti_Patterns:
- "API 응답에 DB 전체 레코드 반환"
- "시스템 프롬프트/알고리즘 파라미터가 API로 노출"
- "공개 리더보드에 이메일/실명 포함"
Representative_Healthy_Patterns:
- "DTO/시리얼라이저로 응답 필드 명시적 제한"
- "비즈니스 민감 정보는 서버 측에서만 접근"
- "PII는 마스킹/해싱 후 노출"
```
### 메커니즘 식별 결과 출력
```
┌──────────────────────────────────────────────────────────────────────┐
│ SECURITY MECHANISM TRACKING │
├──────┬──────────────┬──────────────┬──────────┬─────────────────────┤
│ 코드 │ 차원/메커니즘 │ 위치 │ 강도 │ 우회 가능성 │
├──────┼──────────────┼──────────────┼──────────┼─────────────────────┤
│ A1 │ 인증 아키텍처 │ file:line │ 강/중/약 │ 없음 / 가능 / 확인됨 │
│ A2 │ 인가 아키텍처 │ file:line │ 강/중/약 │ 없음 / 가능 / 확인됨 │
│ ... │ ... │ ... │ ... │ ... │
│ M9 │ 비즈니스 플로우 │ file:line │ 강/중/약 │ 없음 / 가능 / 확인됨 │
│ M10 │ 정보 노출 통제 │ file:line │ 강/중/약 │ 없음 / 가능 / 확인됨 │
└──────┴──────────────┴──────────────┴──────────┴─────────────────────┘
```
---
## Phase 2: 원칙 기반 심층 분석 + 공격 체인
Phase 1의 아키텍처 차원 리뷰에서 발견된 약점을 기반으로,
보안 원칙에 따른 **자유 추론**과 **공격 체인 분석**을 수행합니다.
```yaml
Security_Principles:
Least_Privilege: "모든 주체에 필요한 최소 권한만 부여"
Defense_in_Depth: "단일 보안 레이어가 아닌 다층 방어 구조"
CIA_Triad: "기밀성, 무결성, 가용성"
Secure_Defaults: "기본 설정이 안전한 상태"
Trust_Boundary_Verification: "모든 신뢰 경계에서 데이터 검증"
Attack_Chain_Analysis:
1_공유_엔티티_매핑: "동일 DB 테이블을 참조하는 모든 엔드포인트 그룹화"
2_상태_전이_체인: "엔드포인트 A로 상태 변경 → B가 의도치 않은 동작"
3_권한_에스컬레이션_체인: "일반 기능 조합으로 상위 권한 접근"
4_콘텐츠_오염_체인: "UGC가 집계/변환을 거쳐 공식 채널에 표시"
5_자원_고갈_체인: "Rate limit 분산/우회로 시스템 자원 소진"
6_테넌트_격리_체인: "테넌트 A의 컨텍스트에서 테넌트 B의 데이터 접근/변경"
7_프롬프트_인젝션_체인: "사용자 입력/UGC → RAG/DB → LLM 프롬프트 → 도구 호출 → 시스템 변경"
Free_Exploration_Areas:
Business_Logic: "비즈니스 도메인 고유 위협 추론"
Cryptography: "암호화 코드의 목적 적합성 판단"
Timing_Races: "동시 요청으로 인한 무결성 위반"
Cache_Security: "인증 필요 페이지의 CDN 캐싱, 민감 API 캐싱"
AI_Integration: |
AI/LLM 통합 코드를 식별하고 공격 시나리오를 구성:
1. 프롬프트 인젝션 체인: 입력 → 프롬프트 → LLM → 출력 → 시스템 변경
2. 데이터 유출: 민감 데이터 → 프롬프트 → 외부 API
3. 에이전시 남용: LLM → 도구 호출 → 무제한 시스템 변경
4. RAG 포이즈닝: 악의적 콘텐츠 → 벡터 스토어 → 프롬프트 오염
Multi_Tenancy: |
멀티테넌트 격리 우회 공격 시나리오:
1. 테넌트 필터 누락 쿼리를 통한 교차 데이터 접근
2. 캐시 키 조작으로 다른 테넌트 캐시 데이터 접근
3. 백그라운드 잡에서 테넌트 컨텍스트 누락으로 데이터 혼재
```
---
## Phase 3: 공격 카테고리 분석
### Category 1: 권한 우회 (Authorization Bypass)
```yaml
점검_항목:
AUTH-001: "인증 미들웨어 미적용 엔드포인트 — CRITICAL"
AUTH-002: "JWT 서명 미검증/약한 알고리즘 — CRITICAL"
AUTH-003: "일반 사용자가 관리자 기능 접근 — CRITICAL"
AUTH-004: "타인 리소스 접근(IDOR) — HIGH"
AUTH-005: "서비스키 클라이언트 노출/하드코딩 — CRITICAL"
AUTH-006: "세션 만료/갱신/무효화 결함 — HIGH"
AUTH-007: "인가 로직 클라이언트 측 only — HIGH"
AUTH-008: "BaaS/DB 직접 접근으로 API 인가 우회 — CRITICAL"
AUTH-009: "특권 함수(SECURITY DEFINER 등) 일반 사용자 노출 — CRITICAL"
```
### Category 2: 메시지 변조 (Message Tampering)
```yaml
점검_항목:
TAMP-001: "요청 무결성 미검증 (서명/HMAC 없음) — HIGH"
TAMP-002: "WebSocket 메시지 인증/검증 없음 — MEDIUM"
TAMP-003: "외부 API 응답 검증 없이 신뢰 — HIGH"
TAMP-004: "HTTP(비 TLS) 통신으로 MITM 가능 — HIGH"
TAMP-005: "사용자 입력 HTTP 헤더 삽입(CRLF) — MEDIUM"
```
### Category 3: 데이터 조작 (Data Manipulation)
```yaml
점검_항목:
DATA-001: "SQL 인젝션 — CRITICAL"
DATA-002: "레이스 컨디션(TOCTOU) — HIGH"
DATA-003: "Mass Assignment — HIGH"
DATA-004: "비즈니스 로직 우회(결제/할인/제한) — HIGH"
DATA-005: "안전하지 않은 역직렬화 — CRITICAL"
DATA-006: "파일 업로드 검증 미비 — HIGH"
DATA-007: "상태 머신 레이스(Cross-Endpoint TOCTOU) — HIGH"
DATA-008: "가격/티어 일관성 결여 — HIGH"
DATA-009: "UGC 콘텐츠 파이프라인 인젝션 — HIGH"
DATA-010: "RLS/보안규칙 부재 — CRITICAL"
DATA-011: "마이그레이션 권한 드리프트 — HIGH"
DATA-012: "DB 트리거 컨텍스트 우회 — HIGH"
```
### Category 4: 기타 실전 취약점
```yaml
점검_항목:
ETC-001: "Rate Limiting 우회 — MEDIUM"
ETC-002: "Race Condition / TOCTOU — HIGH"
ETC-003: "의존성 공급망 공격 — MEDIUM"
ETC-004: "CI/CD 파이프라인 보안 — MEDIUM"
```
### Category 5: 공격 체인 분석 (Cross-Endpoint Attack Chain)
개별 엔드포인트는 안전하지만 **조합하면 취약해지는 시나리오**를 탐색합니다.
```yaml
점검_절차:
1_공유_엔티티_매핑: "동일 DB 테이블을 참조하는 모든 엔드포인트 그룹화"
2_상태_전이_체인: "엔드포인트 A로 상태 변경 → B가 의도치 않은 동작"
3_권한_에스컬레이션_체인: "일반 기능 조합으로 상위 권한 접근"
4_콘텐츠_오염_체인: "UGC가 집계/변환을 거쳐 공식 채널에 표시"
5_자원_고갈_체인: "Rate limit 분산/우회로 시스템 자원 소진"
```
### Category 6: 정보 노출 (Information Disclosure)
```yaml
점검_항목:
DISC-001: "API 응답 과다 데이터 (SELECT *, JOIN 과다 노출) — MEDIUM~HIGH"
DISC-002: "PII 노출 (공개 API에 실명/이메일/전화번호) — MEDIUM~HIGH"
DISC-003: "비즈니스 민감 정보 (수익 배분, 알고리즘 파라미터) — LOW~MEDIUM"
DISC-004: "JWT 토큰 과다 클레임 — MEDIUM"
DISC-005: "비활성 엔티티 정보 접근 — MEDIUM"
```
### Category 7: 비즈니스 로직 남용 (Business Logic Abuse)
```yaml
점검_항목:
BIZ-001: "필수 플로우 단계 스킵 — HIGH"
BIZ-002: "유료 리소스 무료 접근 — HIGH"
BIZ-003: "타인 리소스 조작 — HIGH"
BIZ-004: "엔티티 상태 직접 조작 — HIGH"
BIZ-005: "비활성 엔티티 남용 — MEDIUM~HIGH"
BIZ-006: "무제한 리소스 생성 — MEDIUM~HIGH"
# ─── P2-4 확장: 원자성/결제/경제 공격 ───────────────────────
BIZ-007: "Single-Packet Atomicity — 동일 요청 N개 병렬 → N회 처리 (CRITICAL)"
BIZ-008: "Idempotency Key Replay — 같은 key + 다른 body → 이중 처리 (HIGH)"
BIZ-009: "Coupon Stacking — 쿠폰 A+B+A 재사용으로 누적 할인 (HIGH)"
BIZ-010: "Email+Alias Bypass — user@x.com vs user+tag@x.com 동치 처리 누락 (MEDIUM)"
BIZ-011: "Negative Amount — 음수 금액 수용으로 무료/이익 창출 (CRITICAL)"
BIZ-012: "Currency Rounding — 소수점 절사로 누적 이익 (LOW~MEDIUM)"
BIZ-013: "State Machine Skip — draft→review→published 흐름에서 published 직행 (HIGH)"
BIZ-014: "Partial Refund Loop — 부분 환급을 N회 반복 → 원금 초과 환급 (HIGH)"
BIZ-015: "Airdrop / Free-trial Farming — 동일 디바이스에서 계정 생성 무제한 (MEDIUM)"
```
#### BIZ-007~015 방법론 가이드
```yaml
Single_Packet_Attack:
원리: |
HTTP/1.1 또는 HTTP/2 환경에서 동일 state-changing 요청 N개를 하나의
TCP 세그먼트에 모아 전송 (curl --parallel 또는 Turbo Intruder의
last-byte sync) → 서버가 순차 처리 전 N개가 거의 동시 도착 →
read-check-write 사이 race로 잔액/재고/쿠폰 N배 소진 가능.
대상_시나리오:
- 잔액 출금 (balance --)
- 쿠폰 소진 (coupon.used = true)
- 재고 차감 (stock --)
- 좋아요/투표 unique 제약
PoC_Template: |
# Python asyncio 예시 (3건 병렬)
import asyncio, aiohttp
async def one(s):
async with s.post(URL, headers=H, json={"amount":100}) as r:
return r.status
async def main():
async with aiohttp.ClientSession() as s:
results = await asyncio.gather(*[one(s) for _ in range(3)])
print(results)
성공_판정:
- 서버 응답 3건 모두 200 + 잔액이 3×100만큼 차감 (State Delta)
- 1건만 성공해야 하는 세마틱이면 원자적 UPDATE/CAS 부재 확정
Idempotency_Replay:
원리: |
결제/송금 API가 Idempotency-Key를 받을 때, 같은 key 재요청 시 기존 결과를
리턴하지 않고 body가 다르면 재처리 → 공격자가 key는 유지하고 body만 바꿔
2회 과금 가능.
테스트: |
1. 1회 결제 요청 (key=X, amount=100) → 200 OK, 거래 1건
2. 같은 key=X로 amount=1 로 재요청 → 정상이면 200 OK + 기존 거래 리턴
취약이면 amount=1 신규 거래 생성
3. State Delta: 거래 건수가 1건 유지되면 정상, 2건이면 취약
Negative_Amount:
테스트: |
금액 필드에 -100, "-100", -0.01, -9e99 삽입
→ UI는 차단해도 API가 수용하면 음수 입금/음수 출금 → 이익 창출
파생: "쿠폰 금액 마이너스, 할인율 120% 입력"
Email_Alias_Bypass:
테스트: |
회원가입에서 user@x.com 존재 시 user+tag@x.com, user.@x.com,
USER@x.com, user@X.com 등이 동일 이메일로 간주되어야 함.
그렇지 않으면 1인당 1회 쿠폰이 N회 가능.
State_Machine_Skip:
테스트: |
draft → review → published의 워크플로우에서 직접 /api/posts/:id
{ status: "published" } PATCH 요청이 수용되는지.
서버가 현재 status + 허용 전이 매트릭스로 검증해야 함.
```
### Category 8: AI/LLM 공격 (AI/LLM Exploitation)
```yaml
점검_항목:
AI-001: "직접 프롬프트 인젝션 — 사용자 입력으로 시스템 프롬프트 우회 — HIGH~CRITICAL"
AI-002: "간접 프롬프트 인젝션 — RAG/DB 데이터로 프롬프트 오염 — HIGH"
AI-003: "LLM 출력 기반 코드 실행/인젝션 — CRITICAL"
AI-004: "시스템 프롬프트 추출 — MEDIUM~HIGH"
AI-005: "민감 데이터 LLM 유출 (PII/시크릿이 프롬프트에 포함) — HIGH"
AI-006: "에이전트 권한 남용 (승인 없는 도구 호출로 시스템 변경) — HIGH~CRITICAL"
AI-007: "모델 DoS (의도적 토큰 소진 공격) — MEDIUM"
AI-008: "RAG 데이터 포이즈닝 (벡터 스토어에 악의적 콘텐츠 주입) — HIGH"
```
### Category 9: 모바일 플랫폼 공격 (Mobile Platform Exploitation)
```yaml
점검_항목:
MOB-001: "안전하지 않은 로컬 저장소에 자격 증명 저장 — HIGH"
MOB-002: "Deep Link/URL Scheme 인젝션 — MEDIUM~HIGH"
MOB-003: "인증서 피닝 미적용 또는 우회 가능 — MEDIUM"
MOB-004: "네트워크 보안 설정 과도한 예외 (cleartext, ATS 비활성화) — MEDIUM"
MOB-005: "로컬 DB 암호화 미적용 — MEDIUM~HIGH"
MOB-006: "민감 데이터 로그 기록 — MEDIUM"
MOB-007: "생체 인증 로컬 우회 가능 (boolean 체크만) — HIGH"
MOB-008: "WebView JavaScript 인터페이스 과도한 권한 — HIGH"
MOB-009: "바이너리 내 하드코딩 시크릿 — HIGH"
```
### Category 10: SDK 오용 및 남용 (SDK Misuse & Abuse)
> SDK 도메인이 활성인 경우에만 수행합니다.
> SDK 제공자 관점에서 소비자의 오용과 공격자의 남용 시나리오를 분석합니다.
```yaml
점검_항목:
# Secure Defaults (안전한 기본값)
SDK-001: "기본 설정이 안전하지 않음 (HTTP 허용, 인증서 검증 비활성화 등) — HIGH"
SDK-002: "디버그 로깅이 릴리즈에서 기본 활성화 — 민감 정보 노출 — HIGH"
SDK-003: "위험 옵션(disableSsl, debugMode) 활성화 시 경고/차단 없음 — MEDIUM"
# Credential Management (자격 증명 관리)
SDK-004: "API 키/토큰이 로그, 에러 메시지, toString()에 노출 — HIGH"
SDK-005: "자격 증명이 비암호화 로컬 저장소에 저장 — HIGH"
SDK-006: "SDK 해제 시 메모리/로컬 저장소에 자격 증명 잔류 — MEDIUM"
# API Surface (공개 API 표면)
SDK-007: "내부 전용 API가 외부에서 접근 가능 (접근 제어 누락) — HIGH"
SDK-008: "초기화 미완료 상태에서 API 호출 가능 — 인증 우회 — CRITICAL"
SDK-009: "설정 객체 참조가 외부에서 변경 가능 — 런타임 설정 조작 — HIGH"
SDK-010: "Deprecated 비안전 API가 경고/차단 없이 동작 — MEDIUM"
# Data Flow (데이터 흐름)
SDK-011: "SDK가 문서화되지 않은 데이터를 백엔드에 자동 전송 — MEDIUM~HIGH"
SDK-012: "백엔드 응답의 다른 사용자 민감 정보가 개발자 콜백으로 전달 — HIGH"
SDK-013: "SDK 로컬 캐시에 민감 데이터 평문 잔류 — 앱 삭제 후에도 — HIGH"
# Network Security (네트워크 보안)
SDK-014: "HTTPS 실패 시 HTTP 폴백 — 전송 보안 하향 — CRITICAL"
SDK-015: "인증 실패 시 비인증 폴백 — 인증 우회 — CRITICAL"
SDK-016: "재시도 로직에 지수 백오프 없음 — 서버 과부하 유발 — MEDIUM"
SDK-017: "Certificate Pinning 미지원 / MITM 공격 취약 — MEDIUM~HIGH"
# Resource Management (리소스 관리)
SDK-018: "무한 재시도 / 무제한 폴링으로 배터리/네트워크 소진 — MEDIUM"
SDK-019: "캐시/로컬 저장 크기 제한 없음 — 저장공간 소진 — LOW~MEDIUM"
SDK-020: "연결(WebSocket, TCP) 미해제 — 리소스 누수 — MEDIUM"
# Distribution (배포)
SDK-021: "배포 산출물에 소스맵/심볼/디버그 정보 포함 — 내부 구조 노출 — MEDIUM"
SDK-022: "아티팩트 서명 미적용 — 공급망 공격 — HIGH"
SDK-023: "전이 의존성에 알려진 CVE — 소비자 앱 전체에 영향 — HIGH"
점검_절차:
1_Secure_Default_Audit: |
SDK 초기화 코드를 분석하여 모든 기본값을 열거하고,
각 기본값이 "가장 안전한 설정"인지 평가한다.
개발자가 명시적으로 보안을 낮추지 않는 한
기본 상태에서 안전해야 한다.
2_Credential_Lifecycle_Trace: |
자격 증명이 SDK 내부에서 거치는 전체 생명주기를 추적:
수신 → 저장 → 사용(요청 포함) → 갱신 → 폐기
각 단계에서 노출/유출 경로를 식별한다.
3_API_Surface_Enumeration: |
export/public으로 노출된 모든 API를 열거하고,
의도치 않은 내부 API 노출, 초기화 순서 우회,
설정 조작 가능성을 분석한다.
4_Data_Flow_Mapping: |
개발자→SDK, SDK→백엔드, 백엔드→SDK→개발자 3방향
데이터 흐름을 매핑하고, 각 경로에서
민감 데이터 노출/수집/잔류를 분석한다.
5_Network_Resilience: |
네트워크 장애, MITM, 서버 점검 등 비정상 상황에서
SDK의 폴백/재시도 동작이 보안을 하향시키는지 분석한다.
6_Distribution_Audit: |
빌드 산출물의 내용, 서명, 의존성을 감사하여
공급망 공격 경로와 정보 노출을 식별한다.
```
---
## Phase 3.5: 창의적 공격 추론 (Creative Attack Reasoning)
> Phase 1~3의 체크리스트 기반 분석이 완료된 후,
> 체크리스트에 없는 이 프로젝트 고유의 공격 시나리오를 자유 추론합니다.
```yaml
Creative_Attack_Reasoning:
목적: |
Phase 3까지는 알려진 취약점 카테고리(AUTH, TAMP, DATA 등)를 탐색한다.
이 단계는 카테고리에 포함되지 않는 프로젝트 고유의 공격 가능성을
공격자의 관점에서 자유롭게 추론한다.
접근_방식:
Asset_Driven: |
"이 시스템에서 가장 가치 있는 자산은 무엇인가?"
→ 자산을 식별하고, 그 자산을 탈취/변조/파괴하는 경로를 역추적한다.
예: 자금, 개인키, 사용자 데이터, 비즈니스 로직 상태, API 크레딧
Weakness_Composition: |
"Phase 1~3에서 발견된 개별 약점들을 비자명하게 조합하면 어떤 시나리오가 가능한가?"
→ 개별적으로는 MEDIUM이지만 조합하면 CRITICAL이 되는 체인을 탐색한다.
Phase 2 Attack_Chain_Analysis의 7개 체인 유형에 한정되지 않는다.
Architecture_Specific: |
"이 아키텍처에서만 가능한 공격이 있는가?"
→ 기술 스택, 배포 모델, 데이터 흐름의 고유 특성에서 발생하는 공격을 추론한다.
예: 마이크로서비스 간 내부 통신 신뢰, 이벤트 소싱의 재생 공격,
서버리스 콜드 스타트 타이밍 차이, 멀티테넌트 캐시 키 충돌
Defender_Blind_Spot: |
"개발자가 예상하지 못했을 공격 경로가 있는가?"
→ 정상 사용 흐름에서 벗어나되, 시스템이 기술적으로 허용하는 경로를 탐색한다.
예: API 스펙에 없지만 서버가 수용하는 파라미터, 문서화되지 않은 엔드포인트,
에러 핸들링 경로에서만 도달하는 코드, 마이그레이션 중 발생하는 일시적 상태
실행_절차:
1_자산_식별: "코드 분석에서 파악된 핵심 자산 3~5개를 열거한다"
2_공격_목표_설정: "각 자산에 대해 '탈취/변조/서비스 거부' 목표를 설정한다"
3_경로_추론: |
목표 달성을 위한 공격 경로를 자유롭게 추론한다.
Phase 3 체크리스트와 중복되는 단순 반복은 금지한다.
코드에서 경로의 실현 가능성을 확인하되, 확증 없이 단정하지 않는다.
4_시나리오_기록: |
도출된 시나리오를 아래 구조로 기록한다:
Creative_Attack_Scenarios:
- scenario_id: "CAS-{NNN}"
target_asset: "[공격 대상 자산]"
attack_goal: "[목표: 탈취/변조/거부]"
attack_path: "[공격 경로 설명]"
related_findings: ["F-XXX", "F-YYY"]
feasibility: "Likely | Possible | Speculative"
evidence: "[코드 근거 file:line 또는 추론 근거]"
제약:
- "Phase 3 체크리스트 항목의 단순 반복 금지"
- "최소 1개의 시나리오를 도출 시도해야 함"
- "시나리오가 없으면 '없음 — 추가 공격 경로 미식별'로 기록, 억지 생성 금지"
- "feasibility: Speculative인 시나리오는 보고서에 포함하되 심각도를 부여하지 않음"
- "feasibility: Likely/Possible인 시나리오는 Phase 4에서 POC 생성 대상"
Phase_3_체크리스트와의_관계: |
Phase 3은 "알려진 취약점 유형을 이 프로젝트에서 찾는" 연역적 접근이다.
Phase 3.5는 "이 프로젝트의 구조에서 어떤 공격이 가능한가"를 묻는 귀납적 접근이다.
둘은 상호 보완적이며, Phase 3.5는 Phase 3을 대체하지 않는다.
```
---
## Phase 4: POC 생성
### POC 생성 규칙
```yaml
생성_규칙:
간단한_취약점:
조건: "단일 HTTP 요청 또는 간단한 코드로 검증 가능"
형태: "보고서 내 인라인 코드 블록 (curl 또는 코드 스니펫)"
복잡한_취약점:
조건: "다단계 시나리오, 상태 관리, 동시성 테스트 필요"
형태: "독립 실행 가능한 스크립트 파일 (poc/ 디렉토리)"
실행_모드:
dry_run: "기본 모드. 구조 분석만, 실제 요청 미전송"
live: "--url 옵션 사용 시에만 실제 HTTP 요청 전송"
안전_원칙:
- "파괴적 작업 POC는 반드시 주석으로 경고"
- "프로덕션 환경 대상 POC는 읽기 전용 검증만"
- "모든 POC에 롤백/정리 절차 포함"
```
### POC 포함 요소
```yaml
POC_구조:
1_취약점_설명: "F-ID, 차원, 공격 시나리오"
2_전제_조건: "필요한 인증 토큰/계정, 대상 URL, 환경"
3_실행_코드: "dry-run(기본) / live 모드"
4_성공_판정_기준: "예상 응답, 취약/안전 비교, 자동 Pass/Fail"
5_수정_가이드: "코드 수정 방향, 보안 패턴, 참조 문서"
```
---
## Phase 4.5: 분석 결과 자체 검증 (Self-Verification)
> 모든 모드(dry-run / live)에서 실행됩니다.
> Phase 1~5에서 도출된 Finding을 보고서에 기록하기 전에 자체 검증합니다.
```yaml
Self_Verification:
목적: |
분석 결과의 오탐(과대 평가)과 미탐(누락)을 최소화한다.
각 Finding에 대해 아래 3단계를 실행한다.
Step_1_도달_가능성_검증:
설명: "취약 코드가 실제 실행 경로에서 호출되는가?"
절차:
- "취약 함수/메서드의 호출자(caller)를 코드 전체에서 검색"
- "호출자 0건 → Dead Code 태그, 심각도 재평가"
- "호출자 존재 → 호출 경로(entry point → ... → 취약 함수)를 기록"
Step_2_보상_제어_확인:
설명: "다른 레이어에서 동일 위협을 차단하는 보상 제어가 있는가?"
프로토콜: "common/compensating-control.md의 4단계 프로토콜을 실행한다."
절차:
- "Step 1: 위협 경로의 모든 레이어를 순회한다"
- "Step 2: 각 레이어에서 후보 보상 제어를 식별한다"
- "Step 3: 5개 질문(범위/정밀도/우회가능성/완전성/독립성)으로 유효성을 검증한다"
- "Step 4: Effective/Partial/Ineffective/Unverifiable로 판정하고 기록한다"
원칙:
- "보상 제어의 존재 ≠ 위협 차단 — 유효성이 코드에서 입증되어야 한다"
- "Effective 판정 외에는 원래 심각도를 유지한다"
Step_3_로컬_PoC_검증:
설명: "코드 분석 결론을 로컬 실행으로 확인 가능한가?"
조건: "라이브 환경 접근 없이, 대상 코드를 로컬에서 실행 가능한 경우"
절차:
- "SDK/라이브러리: 의존성 설치 후 취약 함수를 직접 호출하는 스크립트 작성"
- "독립 함수: 함수 로직을 재현하는 최소 스크립트로 동작 확인"
- "설정 기반: 설정 파일/환경 변수 조합으로 위험 동작 재현"
예시:
JWT_미검증: |
jose 라이브러리의 decodeJwt()에 alg:none 위조 토큰을 전달하여
valid=true 반환 여부를 로컬에서 확인
JWT_알고리즘_혼동_HS_RS: |
RS256으로 발급된 토큰을 HS256으로 검증하는 경로에 대해,
IdP 공개키(PEM)를 HMAC 시크릿으로 사용하여 서명한 토큰이
수용되는지 로컬 PoC로 확인:
```python
import jwt
pubkey = open("idp.pem").read()
forged = jwt.encode({"sub":"admin"}, pubkey, algorithm="HS256")
# 대상 검증기가 수용하면 → HS/RS 혼동 취약
```
JWT_kid_경로_주입: |
kid 헤더에 `../../dev/null` 또는 `../../tmp/attacker.key`를 넣어
검증기가 해당 경로를 키로 로드하는지 확인 (file read / RCE 전제).
JWT_jku_조작: |
jku 헤더를 공격자 호스팅 JWKS URL로 설정하고, 해당 jwks에서
자신의 공개키로 위조 서명 검증이 통과하는지 확인.
jwks_uri allowlist 없을 시 취약.
OAuth_state_재사용: |
authorize 요청 2회로 state=A를 재수집 → 2번째 callback에 이전 state를
재사용하여 CSRF/계정 바인딩 공격 가능한지 확인.
OAuth_redirect_uri_우회: |
등록된 `https://app.example.com/callback`에 대해 다음 변형을 시도:
- https://app.example.com.attacker.com/callback
- https://app.example.com/callback/../admin
- https://app.example.com/callback?x=https://attacker.com
- https://app.example.com@attacker.com/callback
성공 시 authorization code 탈취 가능.
로깅_유출: |
프로덕션 모드(IS_DEV=false)에서 커스텀 로거 주입 후
민감 데이터 캡처 여부를 로컬에서 확인
설정_변조: |
SDK 인스턴스의 config 객체를 외부에서 교체 가능한지
Object.isFrozen() 등으로 로컬 확인
판정:
로컬_재현_성공: "Locally Verified — 코드 분석 결론 뒷받침"
로컬_재현_실패: "코드 분석 결론 재검토 — 오탐 가능성"
로컬_실행_불가: "Code Review Only — 로컬 검증 불가 명시"
적용_우선순위: |
모든 Finding에 Step 1~2는 필수. Step 3은 CRITICAL/HIGH Finding에 권장.
LOW/MEDIUM은 Step 1~2만으로 충분.
```
---
## Phase 6.0: 엔드포인트 전수 스윕 (Endpoint Sweep)
> `--url` 옵션이 제공된 경우, Phase 6 Finding 검증 **이전에** 실행됩니다.
> Phase 0-4 엔드포인트 인벤토리의 **모든 외부 표면**을 대상으로 기본 보안 테스트를 수행합니다.
### 목적과 위치
```yaml
목적: |
코드 분석(Phase 1~5)은 "발견된 취약점"만 Phase 6에 전달한다.
코드 분석이 놓친 취약점이 있는 엔드포인트는 Phase 6에서도 테스트되지 않는다.
Phase 6.0은 이 구조적 갭을 해소한다:
- Phase 0-4 인벤토리의 모든 엔드포인트에 Finding 유무와 무관하게 기본 테스트 실행
- 코드 분석에서 놓친 런타임 취약점 발견 (미들웨어 순서, 프레임워크 기본 엔드포인트 등)
- Sweep에서 발견된 이상 항목은 신규 Finding 후보로 Phase 6 Route A~F에 주입
실행_순서: |
Test_Context_Collection (기존) → Phase 6.0 Sweep → Phase 6 Finding 검증 (Route A~F)
Sweep 결과의 신규 Finding 후보는 Phase 6 Route에 추가되어 심층 검증된다.
입력: |
- Phase 0-4: API 엔드포인트 인벤토리 (전체 목록 + AUTH 태깅)
- Phase 0-3: Attack Surface Map (Entry_Points, Auth_Topology)
- Test_Context_Collection에서 수집한 BASE_URL, 인증 토큰
```
### Sweep 카테고리
```yaml
Sweep_1_Auth_Gate_Verification:
목적: "인증 필수 엔드포인트가 실제로 비인증 요청을 거부하는지 전수 확인"
입력: "Phase 0-3 Entry_Points 중 AUTH: yes 태깅된 전체 엔드포인트"
절차:
1: "각 엔드포인트에 인증 헤더 없이 요청 전송 (GET → GET, POST → POST, 동일 메서드)"
2: "응답 코드 수집: 401/403 = PASS, 200/201/202/2xx = FAIL, 5xx = ERROR"
3: "FAIL 항목은 신규 Finding 후보 (AUTH-001: 인증 미들웨어 미적용)"
판정_주의: |
200 응답이 반드시 취약은 아님:
- 공개 API가 코드 분석에서 AUTH: yes로 오태깅된 경우 (FP)
- 응답 본문이 빈 데이터/제한된 데이터면 부분 보호 가능
FAIL 항목은 반드시 응답 본문을 확인하여 실제 데이터 노출 여부를 판별한다.
최적화: |
엔드포인트 50개 이상 시 샘플링 전략:
- state-changing (POST/PUT/PATCH/DELETE) 엔드포인트는 전수 테스트
- read-only (GET) 엔드포인트는 라우트 그룹별 대표 1개 + 랜덤 20% 샘플
- auth_opt_out_routes (Phase 0-3에서 명시적 제외된 경로)는 전수 테스트
Sweep_2_Method_Probing:
목적: "정의되지 않은 HTTP 메서드로 요청 시 서버가 적절히 거부하는지 확인"
입력: "Phase 0-4 인벤토리에서 각 엔드포인트의 정의된 메서드"
절차:
1: "각 엔드포인트에 정의되지 않은 메서드 1개를 전송 (GET-only → POST 시도)"
2: "405 Method Not Allowed = PASS, 200/2xx = FAIL"
3: "FAIL 중 state-changing 메서드(POST/PUT/PATCH/DELETE) 성공 시 → 신규 Finding 후보"
범위_제한: |
- GET-only 엔드포인트에 DELETE/PUT 시도 (최대 위험)
- 이미 POST+GET이면 PATCH/DELETE 시도
- OPTIONS/HEAD는 스킵 (일반적으로 무해)
판정_주의: |
프레임워크가 모든 메서드를 동일 핸들러로 라우팅하는 경우 (예: Next.js route.ts)
코드 내부에서 method 분기 여부를 Phase 1~3 코드 분석 결과와 대조한다.
Sweep_3_Hidden_Endpoint_Discovery:
목적: "Recon이 추론한 자동 노출 엔드포인트(Auto_Exposed_Endpoints)를 라이브로 검증"
입력: |
Phase 0 Recon의 Auto_Exposed_Endpoints 결과를 그대로 사용한다.
Sweep_3은 자율 추론을 수행하지 않는다 (재현성 보장 + 책임 분리).
상세: skills/ch015/common/recon.md → Phase 0-4 → Auto_Exposed_Endpoints_Inference
원칙:
No_Inference_Here: |
"엔드포인트 추론은 Recon의 책임. Sweep_3는 검증만 수행.
Recon이 못 잡은 후보를 Sweep_3가 자체 추론하면 재현성이 무너진다."
Reproducibility: |
"동일 프로젝트 재실행 시 동일 후보 검증. AI 변동성 차단."
절차:
1_입력_확인: |
Recon 출력의 Auto_Exposed_Endpoints 목록 로드.
비어있으면 → '미감지 — Recon 보강 필요' 경고 출력 후 Sweep_3 종료.
2_프로빙: |
각 후보 path에 GET 요청 전송 (인증 없이 / 있으면 표준 인증으로).
3_응답_분석: |
200 응답 시 본문 분석:
- 민감 정보 포함 (스택 트레이스, 환경변수, 내부 구조, API 명세, 사용자 데이터 등)
- 프레임워크 정보 노출 (버전, 배포 환경)
4_Finding_생성: |
민감 정보 노출 확인 시 신규 Finding 후보 (F-S{NNN}).
Recon 출력의 evidence(의존성/설정 file:line)를 Finding 증거에 포함.
Recon_미보강_경고: |
Auto_Exposed_Endpoints가 비어있거나 명백히 불충분해 보이면:
1) Sweep_3 결과에 'Recon Auto_Exposed_Endpoints inference 보강 필요' 경고 명시
2) Sweep_3 자체 추론은 금지 — 추론 책임은 Recon에만 있음
3) Lead/CISO에게 Recon 재실행 권고 가능
안전: "GET 요청만. state-changing 프로빙 금지."
⚠️_철학:
Single_Source_of_Truth: "엔드포인트 발견은 Recon, 보안 검토는 VA, 라이브 검증은 Sweep_3 — 책임 명확 분리"
No_Pattern_List_Dependency: "고정 카탈로그 의존하지 않음. 프레임워크 가변성은 Recon AI 추론으로 대응"
Verification_Not_Inference: "Sweep_3는 추론이 아닌 검증 단계 — Recon 결과를 신뢰하고 라이브로 확인"
Sweep_4_Security_Header_Baseline:
목적: "전체 애플리케이션의 보안 헤더 적용 현황을 표본 검사"
절차:
1: "대표 엔드포인트 3~5개 선정 (메인 페이지, API 루트, 인증 엔드포인트)"
2: "HEAD 요청으로 응답 헤더 수집"
3: "누락 헤더 체크: CSP, X-Frame-Options, HSTS, X-Content-Type-Options"
4: "전체 누락 시 단일 Finding (엔드포인트별 개별 Finding 생성 금지)"
판정: |
보안 헤더 부재 자체는 MEDIUM 이하.
Phase 1~5에서 XSS/Clickjacking Finding이 있는 경우에만 심각도 연계.
Sweep_5_CORS_Misconfiguration:
목적: "Origin 반사 또는 와일드카드 허용으로 인한 교차 출처 공격 가능성 확인"
절차:
1: "대표 API 엔드포인트 3~5개에 Origin: https://attacker.example.com 헤더 전송"
2: "Access-Control-Allow-Origin 응답 헤더 확인"
3: |
- 공격자 Origin 그대로 반사 → FAIL (credential 포함 시 CRITICAL)
- * (와일드카드) → 조건부 FAIL (withCredentials 가능 여부에 따라)
- 고정 허용 목록 → PASS
추가_변형: |
반사가 감지되면 추가 테스트:
- null Origin (data: URI, sandboxed iframe)
- 서브도메인 변형 (trusted.com.attacker.com)
- 프로토콜 다운그레이드 (http:// Origin)
```
### Sweep 결과 처리
```yaml
결과_분류:
SWEEP_PASS: "기대대로 동작 — 추가 조치 없음"
SWEEP_FAIL: "이상 탐지 — 신규 Finding 후보"
SWEEP_ERROR: "네트워크/서버 에러 — 재시도 1회 후 기록"
신규_Finding_생성:
절차:
1: "Sweep FAIL 항목을 유형별로 그룹화"
2: "각 그룹에 대해 코드 분석 결과(Phase 1~5)와 대조"
3: |
- 코드 분석에서 이미 Finding으로 보고됨 → 기존 Finding에 라이브 증거 추가
- 코드 분석에서 미발견 → 신규 Finding 후보 생성 (F-S001~)
4: "신규 Finding 후보는 Phase 6 Route A~F에 주입하여 심층 검증"
Finding_ID: "Sweep 발견 Finding은 F-S{NNN} 접두사로 구분 (F-S001, F-S002, ...)"
주의: |
Sweep은 기본 테스트(shallow)이므로 FAIL = 즉시 취약점이 아니다.
반드시 Phase 6 Route의 State Delta 검증, Differential Testing 등으로
심층 확인한 후에만 최종 Finding으로 확정한다.
결과_요약_형식: |
```
┌──────────────────────────────────────────────────────────────┐
│ ENDPOINT SWEEP RESULT │
├──────────────────────────────────────────────────────────────┤
│ 총 엔드포인트: {total} │
│ 테스트 완료: {tested} │
│ PASS: {pass} │
│ FAIL (후보): {fail} → Phase 6 심층 검증 대상 │
│ ERROR: {error} │
├──────────────────────────────────────────────────────────────┤
│ Sweep 카테고리별: │
│ Auth Gate: {s1_pass}/{s1_total} PASS │
│ Method Probe: {s2_pass}/{s2_total} PASS │
│ Hidden EP: {s3_found}건 발견 │
│ Security Hdr: {s4_missing}종 누락 │
│ CORS: {s5_pass}/{s5_total} PASS │
├──────────────────────────────────────────────────────────────┤
│ 신규 Finding 후보: {new_candidates}건 → Phase 6 Route 주입 │
└──────────────────────────────────────────────────────────────┘
```
```
### 안전 원칙 (Phase 6 공통 적용 + Sweep 추가)
```yaml
Sweep_안전:
- "모든 Sweep은 읽기 전용 — state-changing 요청은 Sweep_1의 기존 메서드 재현만"
- "Sweep_1의 POST/PUT/PATCH/DELETE는 빈 body 또는 최소 body로 전송 (실제 변경 방지)"
- "프로덕션 감지 시 Sweep_1은 GET 엔드포인트만 테스트, state-changing은 스킵"
- "요청 간 100ms 이상 간격 유지 (서버 과부하 방지)"
- "5xx 응답 연속 3회 발생 시 해당 Sweep 카테고리 중단 + 사용자 알림"
- "Phase 6 공통 안전 원칙(프로덕션 감지, Rate Limit 제한)이 동일 적용"
```
---
## Phase 6: 라이브 검증 (Live Verification)
> `--url` 옵션이 제공된 경우에만 실행됩니다.
> Phase 6.0 Sweep 완료 후, Finding 기반 심층 검증을 수행합니다.
### 인증 자동 구성
```yaml
자동_구성:
Supabase:
프로젝트_레퍼런스_추출: "코드에서 SUPABASE_URL 탐색 → project_ref 추출"
쿠키_이름: "sb-{project_ref}-auth-token"
쿠키_값: "raw JSON (base64 인코딩 안 함)"
토큰_검증: "인증 필수 엔드포인트에 테스트 요청"
일반:
Bearer_토큰: "Authorization: Bearer {token} 헤더"
API_Key: "X-API-Key: {key} 헤더"
```
### 검증 분류
```yaml
검증_분류:
무인증_검증: "인증 없이 검증 가능 (보안 헤더, 무인증 접근, Rate Limit)"
인증_필요_검증: "유효한 세션/토큰 필요 (비즈니스 로직 결함)"
API_키_검증: "외부 API 키 필요"
검증_불가: "서버 내부 상태 의존 (코드 리뷰만 가능)"
```
### 판정 기준
```yaml
판정:
CONFIRMED: "실제 악용 가능 확인됨 — 상태 변경이 증거로 입증됨"
BLOCKED: "다른 방어 계층에 의해 차단됨"
MITIGATED: "존재하나 영향 제한적"
BLIND_ACCEPT: "API가 성공 응답을 반환하나, 실제 상태 변경 없음 (fire-and-forget 패턴)"
INCONCLUSIVE: "네트워크/타임아웃으로 판정 불가"
NOT_TESTED: "키 미제공 또는 검증 불가능"
```
### 판정 규칙: 응답 vs 실제 효과
```yaml
판정_규칙:
핵심_원칙: |
"API 응답 코드/메시지만으로 취약점을 판정하지 않는다.
반드시 대상 시스템의 상태 변경(State Delta)을 독립적으로 검증해야 한다."
State_Delta_검증:
정의: "POC 실행 전후의 대상 리소스 상태를 비교하여 실제 효과 확인"
절차:
1: "POC 실행 전 대상 리소스의 상태 스냅샷 기록 (GET 요청)"
2: "POC 실행 (POST/PUT/PATCH/DELETE)"
3: "충분한 대기 시간 후 상태 재조회 (비동기 처리 고려)"
4: "전후 스냅샷 diff 분석"
판정:
diff_존재: "CONFIRMED — 실제 상태 변경 발생"
diff_없음_성공응답: "BLIND_ACCEPT — 응답만 성공, 실제 효과 없음"
diff_없음_실패응답: "BLOCKED — 서버에서 명시적 거부"
비동기_처리_대기:
설명: "fire-and-forget, 큐, 배치 처리 등 비동기 아키텍처 고려"
절차:
- "대상 시스템의 비동기 처리 주기를 코드/설정/문서에서 파악"
- "처리 주기 × 3 이상 대기하며 최소 3회 폴링으로 상태 재조회"
- "처리 주기 불명 시: 1초, 5초, 30초 지수 간격으로 폴링"
- "폴링 기간 중 변화가 없으면 최종 판정"
```
### 검증 기법
```yaml
기법_1_Differential_Testing:
목적: "동일 액션을 인증/비인증으로 각각 실행하여 실제 차이를 비교"
핵심_절차:
- "테스트 대상 액션을 정확히 동일하게 정의"
- "비인증 요청 전송 → 응답 기록 + 상태 조회 (비동기 API는 처리 주기 맞춰 폴링)"
- "인증 요청 전송 → 동일 기준으로 응답 기록 + 상태 조회"
- "응답 코드 + 응답 본문 + 상태 변경 3축 비교"
판정:
응답_동일_상태_동일_변경: "CONFIRMED — 인증 없이도 실제 악용 가능"
응답_동일_상태_인증만_변경: "BLIND_ACCEPT — 응답은 동일하나 비인증은 실제 미적용"
응답_다름_상태_다름: "BLOCKED — 서버가 명시적으로 구분"
응답_동일_상태_둘다_미변경: "INCONCLUSIVE — 추가 검증 필요"
키_미보유_시: "비인증 요청만 전송하되 Control Group 기법과 결합하여 자연 변화와 구분"
기법_2_Control_Group_Observation:
목적: "시스템의 자연적 상태 변화와 POC에 의한 변화를 구분"
적용_조건: |
자율 상태 변화가 있는 시스템(배치 잡, 스케줄러, 이벤트 드리븐, 게임 틱 등)에서만 사용.
순수 CRUD API처럼 외부 요청 없이 상태가 바뀌지 않는 시스템에서는 불필요.
절차:
- "실험군(POC 전송)과 대조군(아무 액션 없음) 동일 환경에서 선정"
- "시스템 자율 처리 주기에 맞춰 양쪽 상태를 폴링"
POC_귀인_판정: |
실험군 변화 - 대조군 변화 패턴 = POC 효과
- 실험군에서만 POC와 일치하는 특이 변화 발생 → CONFIRMED
- 양쪽 변화 패턴이 동일 → BLIND_ACCEPT / BLOCKED
- 양쪽 모두 변화 없음 → 시스템 비활성, 재시도 필요
기법_3_Response_Semantics_Analysis:
목적: "API 응답의 구조적 특성으로 실제 처리 여부를 추론"
핵심_신호:
202_Accepted: |
⚠️ 경고 플래그: 비동기 수신 확인(ACK)일 가능성 높음.
응답 본문에 처리 결과가 없으면 fire-and-forget 의심.
별도 폴링/조회로 실제 처리 결과 확인 필수.
최소_응답: |
{success: true} 또는 {accepted: true}만 반환 → fire-and-forget 의심.
특히 상태 변경 API에서 이 패턴은 Blind Accept 가능성 높음.
에러_상세: |
{error: "UNAUTHORIZED", message: "..."} → 서버가 명시적 거부.
이 응답이 인증/비인증 모두에서 나오는지 차등 검증.
Response_Timing: "보조 지표로만 사용. 절대 임계값 판정 금지."
기법_4_Deliberate_Failure_Injection:
목적: "의도적으로 잘못된 요청을 보내 서버의 검증 수준을 탐지"
원리: "실제 처리하는 서버는 구체적 에러 반환. fire-and-forget은 잘못된 요청에도 동일 성공 응답."
테스트_케이스:
- "Invalid_Target: 존재하지 않는 리소스 ID (기대: 404 vs 202)"
- "Invalid_Action: 존재하지 않는 액션 타입 (기대: 400 vs 202)"
- "Impossible_State: 현재 불가능한 액션 (기대: 409 vs 202)"
- "Malformed_Payload: 필수 필드 누락 (기대: 400 vs 202)"
종합_판정: |
- 4개 중 3개 이상에서 동일 성공 응답 → fire-and-forget 확정
- 각각 구체적 에러 반환 → 실제 처리 확인 (차등 검증으로 진행)
- 혼합 → 부분적 검증 (Gateway에서 일부 검증, 나머지는 Module)
기법_5_Multi_Step_Attack_Chaining:
목적: "단일 요청으로 검증 불가한 비즈니스 로직 취약점을 다단계 시나리오로 검증"
적용_대상:
- "비즈니스 플로우 우회 (결제 → 승인 → 배송 단계 스킵)"
- "상태 조작 (리소스 생성 → 권한 변경 → 비인가 접근)"
- "권한 상승 체인 (일반 가입 → 프로필 수정 → 관리자 기능 접근)"
- "레이스 컨디션 (동시 요청으로 잔액 이중 사용)"
- "IDOR 체인 (자원 생성 → ID 추출 → 타 사용자 접근)"
```
### 검증 통합 프로토콜
```yaml
Integrated_Verification_Protocol:
설명: |
라이브 검증의 목표별로 적절한 기법을 선택하여 실행하는 프로토콜.
Finding의 유형에 따라 검증 경로가 분기된다.
검증_경로_선택:
Route_A_비동기_응답_의심:
조건: "API가 202 반환, 또는 {success:true}만 반환하여 실제 처리 여부 불명"
적용_기법:
1: "Response Semantics Analysis — 사전 판별"
2: "Deliberate Failure Injection — fire-and-forget 확정/배제"
3: "Differential Testing 또는 Control Group — State Delta 확인"
판정: "CONFIRMED / BLIND_ACCEPT / BLOCKED"
Route_B_인증_인가_우회:
조건: "비인증 접근, IDOR, 권한 상승 등 접근 제어 취약점"
적용_기법:
1: "Differential Testing — 인증/비인증 또는 사용자A/사용자B 비교"
2: "Multi-Step Attack Chaining — IDOR/권한 상승 시 다단계 시나리오 적용"
3: "State Delta 검증 — 실제 상태 변경 확인"
판정: "CONFIRMED / BLOCKED"
Route_C_정보_노출:
조건: "API 응답 과다 데이터, PII 노출, 내부 정보 노출"
적용_기법:
1: "대상 API 호출 — 응답 본문에 민감 데이터 포함 여부 확인"
2: "인증 수준별 비교 — 비인증/일반/관리자 응답 차이"
판정: "CONFIRMED (민감 데이터 존재) / BLOCKED (필터링 확인)"
Route_D_비즈니스_로직:
조건: "플로우 스킵, 레이스 컨디션, 상태 조작 등 비즈니스 결함"
적용_기법:
1: "Multi-Step Attack Chaining — 다단계 시나리오 구성 및 변수 바인딩"
2: "시나리오 템플릿 중 해당 유형 선택 (비즈니스_플로우_스킵, 권한_상승_체인 등)"
3: "State Delta 검증 — 비즈니스 규칙 위반 상태 도달 여부"
판정: "CONFIRMED / MITIGATED / BLOCKED"
Route_E_Rate_Limit_리소스:
조건: "Rate Limiting, 리소스 소비 제어"
적용_기법:
1: "반복 요청 (최대 30회) — 차단 응답(429) 발생 시점 확인"
2: "차단 후 회복 시간 측정"
판정: "CONFIRMED (미제한) / MITIGATED (제한 존재하나 우회 가능) / BLOCKED"
Route_F_VA_Escalation:
조건: |
VA에서 Unverifiable_HTTP (verification_target: PENTEST)로 분류된
보상 제어가 있는 Finding. offsec-lead가 Pending_Verification 목록에서
PENTEST 대상 항목을 전달한 경우.
목적: |
VA 코드 분석에서 확인 불가했던 보상 제어의 실제 차단 효과를
라이브 HTTP 요청으로 검증하여 FP를 줄인다.
입력: |
Pending_Verification.PENTEST 목록:
- finding_id, control, claim, unverifiable_reason
적용_기법:
1_보상_제어_대상_식별: |
VA가 전달한 claim(검증 대상)을 기반으로 보상 제어의 주장을 파악한다.
테스트 방법은 VA가 지시하지 않으며, Pentest가 Attacker_Mindset으로
자율적으로 결정한다.
- claim에 대해 "이 제어를 어떻게 우회할 수 있는가?"를 질문한다
- 단일 페이로드/요청이 아닌 다양한 변형으로 제어의 실효성을 시험한다
- 기존 Route_A~E 기법을 보상 제어 유형에 맞게 조합 적용한다
2_차단_검증: |
보상 제어가 주장하는 차단을 실제 HTTP 요청으로 시도한다.
- 보상 제어가 차단해야 할 요청 → 차단 응답 확인 (403, 429, 401 등)
- 보상 제어가 허용해야 할 요청 → 정상 응답 확인 (200, 201 등)
3_State_Delta: |
차단 응답이 실제 차단인지 확인 (Route_A 기법 병용):
- 차단 응답 + State Delta 없음 → 실제 차단
- 차단 응답이지만 State Delta 존재 → 차단 우회 가능
판정:
BLOCKED: |
보상 제어가 실제로 위협을 차단함을 라이브로 확인.
→ VA Finding의 심각도를 1단계 하향 근거로 사용.
→ 보상 제어 판정을 Unverifiable → Effective로 재분류.
CONFIRMED: |
보상 제어가 위협을 차단하지 못함을 라이브로 확인.
→ VA Finding의 심각도 유지.
→ 보상 제어 판정을 Unverifiable → Ineffective로 재분류.
PARTIAL: |
보상 제어가 일부 변형만 차단.
→ VA Finding의 심각도 유지 (보수적).
→ 보상 제어 판정을 Unverifiable → Partial로 재분류.
INCONCLUSIVE: |
네트워크/환경 문제로 판정 불가.
→ Unverifiable 유지, 보고서에 사유 기록.
결과_기록: |
VA Finding 원본의 Compensating_Controls 레코드를 업데이트:
- coverage: Unverifiable → Effective/Partial/Ineffective
- verification_target: PENTEST → PENTEST_VERIFIED
- live_evidence: "[curl 명령 + 응답 기록]"
경로_선택_기준: |
AI가 각 Finding의 유형을 판단하여 적절한 경로를 자율 선택한다.
하나의 Finding이 여러 경로에 해당하면 모두 실행한다.
Route_F는 offsec-lead로부터 Pending_Verification 목록을 수신한 경우에만 실행한다.
Sweep_Finding_주입: |
Phase 6.0 Sweep에서 생성된 신규 Finding 후보(F-S{NNN})도
기존 Finding과 동일한 경로 선택 기준으로 Route A~F에 배정한다.
- Auth Gate FAIL → Route_B (인증 우회)
- Method Probe FAIL → Route_B (인증 우회) 또는 Route_D (비즈니스 로직)
- Hidden EP FAIL → Route_C (정보 노출)
- CORS FAIL → Route_B (인증 우회, credential 포함 시)
Sweep Finding은 shallow 테스트 결과이므로 Route에서 심층 검증 후
최종 판정(CONFIRMED/BLOCKED)을 내린다. Sweep FAIL만으로 CONFIRMED 판정 금지.
Control_Group_사용_조건: |
Control Group Observation은 대상 시스템에 자율 상태 변화가
존재하는 경우에만 사용한다. 인증 키 미보유라는 이유만으로
Control Group을 기본 대안으로 사용하지 않는다.
인증 키 미보유 + 자율 변화 없는 시스템 → 무인증 요청의
응답 분석과 Failure Injection만으로 판정한다.
결과_기록_형식: |
각 Finding별 검증 결과를 구조화하여 기록:
```
┌────────────────────────────────────────────────────────────┐
│ LIVE VERIFICATION RESULT │
├──────────────┬─────────────────────────────────────────────┤
│ Finding │ F-XXX │
│ 검증 경로 │ Route_A / B / C / D / E / F │
│ 적용 기법 │ [사용한 기법 목록] │
│ State Delta │ 있음 / 없음 │
│ 최종 판정 │ CONFIRMED / BLIND_ACCEPT / BLOCKED / ... │
│ 심각도 조정 │ 변경 없음 / 변경 사유 │
└──────────────┴─────────────────────────────────────────────┘
```
```
### 안전 원칙
```yaml
안전:
- "프로덕션 URL 감지 시 경고 + 읽기 전용 검증만"
- "파괴적 작업(DELETE, 자금 이동) POC는 dry-run만"
- "Rate Limit 테스트는 최대 30회로 제한"
- "검증 결과에 실제 curl 명령 + 응답을 증거로 기록"
프로덕션_감지: "URL에 staging/stg/dev/test가 없는 경우"
```
### curl 템플릿
```yaml
curl_템플릿:
보안_헤더_확인: |
curl -s -I -X HEAD "$BASE_URL/" | grep -i -E \
"content-security-policy|x-frame-options|strict-transport"
무인증_접근: |
curl -s -w "\nHTTP: %{http_code}" -X POST "$BASE_URL/api/{endpoint}" \
-H "Content-Type: application/json" -d '{payload}'
인증_후_비인가: |
curl -s -w "\nHTTP: %{http_code}" -X POST "$BASE_URL/api/{endpoint}" \
-H "Content-Type: application/json" \
-H "Cookie: {cookie_name}={session_json}" -d '{payload}'
rate_limit: |
for i in $(seq 1 30); do
HTTP=$(curl -s -o /dev/null -w "%{http_code}" ...)
[ "$HTTP" = "429" ] && BLOCKED=$((BLOCKED+1))
done
```
### 사용자 인터랙션
#### Phase 6 진입 시: 테스트 컨텍스트 수집
```yaml
Test_Context_Collection:
목적: |
Phase 6 라이브 검증 시작 전에 필요한 정보를 구조화하여 수집한다.
코드 분석(Phase 1~5)에서 도출된 Finding 유형에 따라
필요한 정보 항목이 달라진다.
수집_시점: "Phase 6 진입 직전, Finding 목록 확정 후"
기본_정보_요청:
설명: |
모든 라이브 검증에 공통으로 필요한 정보를 먼저 요청한다.
사용자에게 아래 양식을 제시하고 입력을 받는다.
양식: |
┌─────────────────────────────────────────────────┐
│ CH015 Pentest — 라이브 검증 준비 │
├─────────────────────────────────────────────────┤
│ │
│ 1. 대상 URL: _______________ │
│ (staging/dev 환경 권장) │
│ │
│ 2. 환경 타입: [ ] staging [ ] dev [ ] prod │
│ (prod 선택 시 읽기 전용 검증만 수행) │
│ │
│ 3. 인증 토큰 (일반 사용자): │
│ Bearer: _______________ │
│ 또는 Cookie: _______________ │
│ │
│ 4. (선택) 관리자 토큰: │
│ Bearer: _______________ │
│ │
│ → 미제공 항목은 해당 검증을 건너뜁니다. │
│ → 추가 정보가 필요하면 검증 중 별도 요청합니다. │
└─────────────────────────────────────────────────┘
Finding_기반_추가_요청:
설명: |
코드 분석에서 도출된 Finding 유형에 따라 추가 정보가 필요한 경우,
기본 정보와 함께 또는 직후에 요청한다.
분류:
IDOR_테스트:
조건: "AUTH-004(IDOR) 또는 인가 관련 Finding 존재"
추가_요청: |
IDOR 검증을 위해 두 번째 계정이 필요합니다:
- 사용자 B 토큰: _______________
- 사용자 A의 리소스 ID (예: agent_id): _______________
- 사용자 B의 리소스 ID: _______________
비즈니스_로직:
조건: "BIZ-001~006 또는 비즈니스 플로우 관련 Finding 존재"
추가_요청: |
비즈니스 로직 검증을 위한 정보:
- 테스트 가능한 리소스 ID: _______________
- 현재 리소스 상태 (활성/비활성): _______________
외부_API:
조건: "외부 API 키가 필요한 Finding 존재"
추가_요청: |
외부 서비스 API Key:
- 서비스명: _______________
- API Key: _______________
관리자_기능:
조건: "AUTH-003(관리자 접근) 관련 Finding 존재"
추가_요청: |
관리자 기능 검증을 위해:
- 관리자 토큰: _______________ (기본 정보에서 미제공 시)
- 관리자 엔드포인트 prefix (예: /admin, /api/admin): _______________
미제공_처리:
원칙: "미제공 항목은 해당 Finding의 검증을 건너뛰고 NOT_TESTED로 기록"
순서:
1: "제공된 정보로 검증 가능한 Finding부터 먼저 실행"
2: "추가 정보가 필요한 Finding 목록을 정리하여 사용자에게 안내"
3: "사용자가 추가 정보 제공 시 나머지 검증 재개"
```
#### 파이프라인 중간 요청 프로토콜
```yaml
Mid_Pipeline_Interaction:
목적: |
라이브 검증 진행 중 추가 정보가 필요하거나,
이전 단계 결과에 따라 새로운 정보가 필요한 경우
사용자에게 단계적으로 요청한다.
요청_트리거:
토큰_만료:
감지: "401 Unauthorized 응답이 이전에 성공했던 요청에서 발생"
메시지: |
⚠️ 세션 토큰이 만료되었습니다.
브라우저에서 새 토큰을 복사해주세요.
현재까지 검증 완료: {completed_count}/{total_count}건
동작: "새 토큰 수신 후 실패한 요청부터 재개"
추가_계정_필요:
감지: "IDOR 테스트 시 두 번째 계정 미제공 상태"
메시지: |
IDOR 검증(F-{id})을 위해 두 번째 계정이 필요합니다.
- 사용자 B의 인증 토큰: _______________
또는 이 Finding은 건너뛰시겠습니까? [건너뛰기/토큰 제공]
동작: "건너뛰기 시 NOT_TESTED, 토큰 제공 시 검증 계속"
리소스_ID_필요:
감지: "특정 리소스 대상 검증 시 유효한 ID 미확보"
메시지: |
F-{id} 검증을 위해 테스트 가능한 리소스 ID가 필요합니다.
- 리소스 타입: {resource_type}
- 예시: {example_id_format}
ID: _______________
동작: "ID 수신 후 해당 Finding 검증 실행"
예상치_못한_응답:
감지: "예상과 다른 응답 구조 (엔드포인트 변경, API 버전 차이 등)"
메시지: |
F-{id} 검증 중 예상과 다른 응답을 받았습니다.
요청: {request_summary}
응답: {response_summary}
이 엔드포인트가 맞습니까? 또는 올바른 경로를 알려주세요.
동작: "사용자 확인 후 재시도 또는 경로 변경"
진행_상태_보고:
타이밍: "5건 이상 Finding 검증 시, 매 5건마다 중간 보고"
형식: |
┌─────────────────────────────────────────────┐
│ 라이브 검증 진행 상황 │
├─────────────────────────────────────────────┤
│ 완료: {done}/{total} │
│ CONFIRMED: {confirmed}건 │
│ BLOCKED: {blocked}건 │
│ NOT_TESTED: {not_tested}건 │
│ 남은 항목 중 추가 정보 필요: {needs_info}건 │
└─────────────────────────────────────────────┘
검증_완료_후:
동작: |
모든 Finding 검증 완료 후, NOT_TESTED 항목이 있으면
사용자에게 추가 정보 제공 의사를 확인한다.
메시지: |
라이브 검증이 완료되었습니다.
- 검증 완료: {tested}건 (CONFIRMED: {c}, BLOCKED: {b})
- 미검증: {not_tested}건 (정보 부족)
미검증 항목에 대해 추가 정보를 제공하시겠습니까?
{미검증 항목 목록 + 각각 필요한 정보}
```
---
## Phase 5R: 규제 영향 참조 (Regulatory Impact Reference)
```yaml
Module: "../va/regulatory.md"
Trigger: |
Phase 1~5에서 발견된 Finding 중 규제 관련성이 있는 것이 1건 이상인 경우에만 실행.
규제 관련 Finding이 0건이면 생략한다.
Scope: |
가상자산, 금융, 개인정보 등 규제 민감 도메인에서 발견된 취약점을
국내외 법률·규제 조항에 매핑하여 참고 정보로 보고서 말미에 첨부한다.
법률 자문이 아니며, 법무팀 에스컬레이션 근거를 제공한다.
상세 프로토콜, 규제 카탈로그, 출력 형식은 모듈 파일 참조.
Key_Principles:
- "법률명 + 조항 번호를 반드시 명시 (모호한 언급 금지)"
- "적용 관할(🇰🇷/🇪🇺/🇺🇸/🌐)을 명시"
- "위반 단정 금지 — '저촉 가능성 있으므로 법무 검토 권장'으로 기술"
- "기술적 심각도를 규제 이유로 변경하지 않음"
```
---
## Root Cause Classification (근본 원인 분류)
```yaml
Root_Cause_Types:
ARCHITECTURE:
description: "시스템 설계 자체의 문제 — 코드 변경만으로 해결 불가"
CONFIGURATION:
description: "기능은 지원되나 설정 누락 — 설정 추가로 해결"
CODE:
description: "로직 오류 또는 검증 누락 — 코드 수정으로 해결"
PROCESS:
description: "개발 프로세스/가이드라인 부재로 반복 발생하는 이슈"
```
## Finding Structure (6-step 영향도 분석)
모든 발견 사항은 아래 6-step 구조를 따릅니다.
**모든 Finding은 마크다운으로 전개해야 하며, 테이블 요약으로 대체 금지.**
> **ID 명명 규칙**: `knowledge-base/conventions/finding-id-naming.md` 참조 (F-/F-S/CAS- 통합 규칙)
```yaml
Finding_Structure:
F-XXX: "[이슈 이름]"
Metadata:
Architecture_Dimension: "A1~A8 / M9 / M10"
Severity: "CRITICAL / HIGH / MEDIUM / LOW"
Preconditions: |
악용에 필요한 전제조건을 열거한다. 없으면 "None".
예: "MITM 위치 확보", "개발자가 위험 설정 활성화",
"사용자가 악성 링크 클릭", "물리적 기기 접근" 등.
심각도는 전제조건을 포함하여 종합적으로 판단한다.
(기계적 심각도 조정 금지 — 영향 범위와 전제조건 난이도를 함께 고려)
Location: "파일, 함수, 설정"
Root_Cause: "ARCHITECTURE / CONFIGURATION / CODE / PROCESS"
Reference:
CWE: "CWE-NNN (필수 — 가장 정확한 CWE ID. 복수 해당 시 쉼표 구분)"
OWASP_Top10: "A01~A10 (필수 — 해당 없으면 'N/A')"
OWASP_API_Top10: "API1~API10 (API 도메인 활성 시 필수, 그 외 선택)"
Note: "CWE/OWASP는 분석의 조직 원리가 아닌 보고서 완전성을 위한 필수 매핑"
Structural_Issue_Description: "구조적 원인 설명"
Evidence: |
코드 참조 (file:line). VA Finding Structure의 Evidence 기준을 동일하게 적용:
판단 기준(위험/안전 동일 증거 기준), 도달 가능성(Reachability),
증거 분류(Observed/Unverified)를 모두 준수한다.
Fix_Recommendation_and_Impact_Analysis:
1_Change_Target: "수정 대상과 방향"
2_Reference_Tracing: "호출/참조 추적"
3_Impact_Scope: "직접/간접 영향"
4_Side_Effect_Risks: "부작용 위험"
5_Co_Requisite_Changes: "동시 수정 항목"
6_Post_Fix_Verification: "검증 항목"
```
No comments yet. Be the first to comment!