diff --git a/troubleshooting/250827_JWT_인증_보안_취약점_CRITICAL.md b/troubleshooting/250827_JWT_인증_보안_취약점_CRITICAL.md index 9dfe878..87bd10d 100644 --- a/troubleshooting/250827_JWT_인증_보안_취약점_CRITICAL.md +++ b/troubleshooting/250827_JWT_인증_보안_취약점_CRITICAL.md @@ -11,10 +11,11 @@ ## 1. 문제 요약 ### 🚨 핵심 문제 -**51124 서버의 대부분 서비스가 JWT 인증 없이 작동** -- X-User-Id 헤더만 신뢰하는 서비스 존재 -- 파라미터로 받은 user_id를 검증 없이 사용 -- Gateway의 일부 엔드포인트가 JWT 검증 누락 +**이중 인증 체계로 인한 보안 취약점** +- **웹 경로**: JWT + UUID 사용 (rb8001 /api/message) +- **Slack 경로**: JWT 없이 Slack ID 사용 (rb8001 /api/slack/events) +- **서비스 간 통신**: 통일된 인증 체계 없음 +- **Gateway**: /api/stats 엔드포인트 JWT 검증 누락 ### 보안 영향 - **인증 우회**: 헤더 조작으로 다른 사용자 행세 가능 @@ -27,67 +28,83 @@ ### 2.1 JWT 인증 구현 상태 -| 서비스 | JWT 인증 | user_id 처리 | Authorization 헤더 | 위험도 | -|--------|---------|--------------|-------------------|--------| -| **rb8001** | ✅ 구현 | UUID (JWT sub) + username | ✅ Bearer 토큰 | 안전 | -| **rb10508_micro** | ❌ 없음 | X-User-Id 헤더만 | ❌ 없음 | 🔴 위험 | -| **skill-email** | ❌ 없음 | 파라미터 "test" | ❌ 없음 | 🔴 위험 | -| **skill-news** | ❌ 없음 | 미구현 | ❌ 없음 | 🟡 중간 | -| **robeing-monitor** | ❌ 없음 | 미구현 | ❌ 없음 | 🟡 중간 | +| 서비스/엔드포인트 | JWT 인증 | user_id 처리 | 현재 상태 | +|-------------------|---------|--------------|----------| +| **rb8001 /api/message** | ✅ 구현 | UUID (JWT sub) | 정상 | +| **rb8001 /api/slack/events** | ❌ 없음 | Slack ID 직접 사용 | Slack 전용 | +| **rb8001 /complete** | ❌ 없음 | "external_service" 고정 | 내부 API | +| **rb10508_micro** | ❌ 없음 | X-User-Id 헤더 신뢰 | 🔴 취약 | +| **skill-email** | ❌ 없음 | 파라미터 user_id | 🔴 취약 | +| **skill-news** | ❌ 없음 | 미사용 중 | - | -### 2.2 Gateway 라우팅 현황 +### 2.2 Frontend API 호출 패턴 -| 엔드포인트 | JWT 검증 | Authorization 전달 | 문제점 | -|-----------|---------|-------------------|--------| -| `/api/chat/*` | ✅ 검증 | ✅ 전달 | 정상 | -| `/api/stats/*` | ❌ 없음 | ❌ 없음 | X-User-Id만 신뢰 | -| `/api/items/*` | ✅ 검증 | ❌ 없음 | 헤더 전달 누락 | +| 엔드포인트 | Frontend에서 보내는 헤더 | Gateway 검증 | +|--------------|------------------------|-------------| +| `/api/chat` | Authorization + X-User-Id | JWT 검증 ✅ | +| `/api/history` | Authorization + X-User-Id | JWT 검증 ✅ | +| `/api/items/gmail` | Authorization + X-User-Id | JWT 검증 ✅ | +| `/api/stats` | X-User-Id만 | 검증 없음 ❌ | --- ## 3. 취약점 상세 -### 3.1 rb10508_micro - 인증 우회 가능 +### 3.1 이중 인증 체계 문제 ```python -# 현재 상태 - 위험 -user_id = request.headers.get("X-User-Id") # 검증 없이 신뢰 -# 공격자가 X-User-Id: "다른사용자UUID" 설정 가능 +# rb8001 - 웹 요청 (/api/message) +@app.post("/api/message") +async def message(auth: str = Depends(verify_jwt_token)): + user_uuid, username = auth # JWT에서 UUID 추출 + +# rb8001 - Slack 요청 (/api/slack/events) +@app.post("/api/slack/events") +async def slack_events(request: Request): + slack_user_id = data.get("user") # JWT 없이 Slack ID 사용 ``` -### 3.2 skill-email - 하드코딩된 기본값 +### 3.2 skill-email - 서비스 간 통신 문제 ```python -# main.py Line 73 -user_id: str = "test" # 하드코딩 -# JWT 검증 전혀 없음 -# 파라미터로 받은 user_id 그대로 사용 +# rb8001에서 skill-email 호출 시 +# 헤더 없이 호출 (Authorization, X-User-Id 모두 없음) +await http_client.post( + "http://skill-email:8501/api/email", + json={"user_id": user_id} # 파라미터로만 전달 +) ``` -### 3.3 Gateway - 일관성 없는 검증 +### 3.3 Gateway - 일부 엔드포인트 JWT 검증 누락 ```python -# /api/stats 엔드포인트 +# /api/stats 엔드포인트 (main.py Line 285) x_user_id: Optional[str] = Header(None) # JWT 검증 없음 -# 누구나 접근 가능 +# 인증 없이 X-User-Id 헤더만 사용 +# /api/chat은 JWT 검증하지만 stats는 누락 ``` --- ## 4. 공격 시나리오 -### 시나리오 1: 타인 이메일 접근 +### 시나리오 1: Slack 경로 인증 우회 ```bash -# 공격자가 skill-email 직접 호출 -curl -X POST http://192.168.219.52:8501/api/email \ +# Slack 이벤트로 위장하여 직접 호출 +curl -X POST http://192.168.219.52:8001/api/slack/events \ -H "Content-Type: application/json" \ - -d '{"user_id": "타겟사용자UUID"}' -# → 타겟 사용자의 이메일 데이터 접근 + -d '{"user": "타겟_slack_id", "text": "명령어"}' +# → JWT 없이 명령 실행 가능 ``` -### 시나리오 2: 통계 조작 +### 시나리오 2: X-User-Id 헤더 조작 ```bash -# 인증 없이 stats 접근 +# rb10508_micro로 직접 호출 +curl http://192.168.219.52:10508/api/chat \ + -H "X-User-Id: 타겟_UUID" +# → JWT 없이 X-User-Id만으로 인증 + +# Gateway /api/stats 호출 curl http://gateway:8100/api/stats/rb8001 \ -H "X-User-Id: 임의UUID" -# → 다른 사용자의 통계 조회/조작 +# → JWT 검증 없이 통계 조회 ``` --- @@ -96,34 +113,39 @@ curl http://gateway:8100/api/stats/rb8001 \ ### 5.1 즉시 조치 (Phase 1) -#### 모든 서비스 JWT 인증 추가 +#### 1. Slack 경로 JWT 추가 또는 분리 ```python -# rb10508_micro, skill-email에 추가 필요 -from app.auth import verify_jwt_token - -async def get_current_user(authorization: str = Header(...)): - if not authorization.startswith("Bearer "): - raise HTTPException(401, "Invalid authorization") - token = authorization.replace("Bearer ", "") - user_uuid, username = verify_jwt_token(token) - return user_uuid +# 옵션 1: Slack 이벤트에도 JWT 요구 +@app.post("/api/slack/events") +async def slack_events( + request: Request, + auth: Optional[str] = Depends(verify_jwt_optional) +): + if not auth: + # Slack 서명 검증로 대체 + verify_slack_signature(request) + +# 옵션 2: Slack과 웹을 완전 분리 +# Slack 전용 서비스로 분리 고려 ``` -#### Gateway 모든 엔드포인트 JWT 검증 +#### 2. Gateway /api/stats JWT 검증 추가 ```python -# main.py 수정 +# Gateway main.py Line 283 수정 @app.get("/api/stats/{robeing_id}") async def get_stats( robeing_id: str, x_user_id: str = Depends(get_verified_user) # JWT 검증 추가 ): + # 현재는 x_user_id: Optional[str] = Header(None)로 취약 ``` ### 5.2 중기 개선 (Phase 2) -1. **통합 인증 미들웨어** - - 모든 서비스에 공통 JWT 검증 미들웨어 - - X-User-Id 헤더 완전 제거 +1. **인증 체계 통합** + - Slack과 웹 경로 통합 또는 명확한 분리 + - 모든 서비스에 일관된 인증 정책 + - X-User-Id 헤더 직접 신뢰 제거 2. **서비스 간 통신 보안** - 내부 API 키 또는 mTLS 적용 @@ -139,8 +161,8 @@ async def get_stats( | 영역 | 영향도 | 설명 | |-----|-------|------| -| **보안** | 🔴 극심 | 인증 우회로 전체 시스템 침해 가능 | -| **데이터** | 🔴 극심 | 타인 데이터 접근 및 조작 가능 | +| **보안** | 🔴 높음 | X-User-Id 헤더 조작으로 인증 우회 가능 | +| **데이터** | 🔴 높음 | 타인 데이터 접근 가능 (조회 위주) | | **서비스** | 🟡 중간 | 일부 서비스만 영향 | | **사용자** | 🔴 높음 | 개인정보 유출 위험 | @@ -150,11 +172,11 @@ async def get_stats( | 우선순위 | 작업 | 담당 | 예상 시간 | |---------|-----|------|----------| -| 1 | skill-email JWT 인증 구현 | 로컬 개발자 | 2시간 | -| 2 | rb10508_micro JWT 인증 구현 | 로컬 개발자 | 2시간 | -| 3 | Gateway /api/stats JWT 검증 추가 | 로컬 개발자 | 1시간 | -| 4 | X-User-Id 헤더 의존성 제거 | 로컬 개발자 | 3시간 | -| 5 | 통합 테스트 및 검증 | 51123 관리자 | 2시간 | +| 1 | Gateway /api/stats JWT 검증 추가 | 로컬 개발자 | 1시간 | +| 2 | rb8001 Slack 경로 인증 강화 | 로컬 개발자 | 2시간 | +| 3 | rb10508_micro JWT 구현 | 로컬 개발자 | 2시간 | +| 4 | skill-email 서비스 간 인증 | 로컬 개발자 | 3시간 | +| 5 | 통합 테스트 | 51123 관리자 | 2시간 | --- @@ -174,9 +196,10 @@ curl -X GET http://gateway:8100/api/stats/rb8001 \ ``` ### 8.2 서비스별 검증 -- rb10508_micro: JWT 없이 접근 → 401 -- skill-email: JWT 없이 접근 → 401 -- Gateway 모든 엔드포인트: JWT 검증 확인 +- Gateway /api/stats: JWT 없이 접근 → 401 +- rb8001 /api/slack/events: Slack 서명 검증 확인 +- rb10508_micro: JWT 또는 대체 인증 구현 확인 +- skill-email: 서비스 간 인증 방식 확인 --- @@ -190,13 +213,20 @@ curl -X GET http://gateway:8100/api/stats/rb8001 \ ## 10. 결론 -**🔴 즉시 조치 필요 - 심각한 보안 취약점** +**🔴 이중 인증 체계 문제 - 통합 필요** -현재 51124 서버의 대부분 서비스가 JWT 인증 없이 작동하여 인증 우회가 가능한 상태입니다. -특히 skill-email과 rb10508_micro는 헤더 조작만으로 타인 데이터에 접근할 수 있어 즉시 수정이 필요합니다. +확인된 주요 문제: +1. **웹 vs Slack**: JWT/UUID vs Slack ID 이중 체계 +2. **Gateway**: /api/stats 엔드포인트 JWT 검증 누락 +3. **서비스 간 통신**: 통일된 인증 없이 파라미터 신뢰 +4. **rb10508_micro**: X-User-Id 헤더만 신뢰 + +모든 경로에 일관된 인증 체계를 구축하거나, Slack과 웹을 명확히 분리해야 합니다. 모든 서비스에 JWT 인증을 구현하고, Gateway에서 일관된 검증을 수행해야 합니다. --- -*작성 완료: 2025-08-27 18:30* \ No newline at end of file +*최종 수정: 2025-08-27 19:30* +*수정 내용: 실제 확인된 사실 기반으로 전면 재작성* +*확인 경로: 51124 서버 조사, 로컬 코드 분석, Gateway 코드 검토* \ No newline at end of file