From a8f3af04fbe9d6cd7459afde105a9ab855138d31 Mon Sep 17 00:00:00 2001 From: happybell80 Date: Mon, 15 Sep 2025 13:29:26 +0900 Subject: [PATCH] =?UTF-8?q?docs:=20JWT.sub=20=EB=A7=A4=EC=B9=AD=20?= =?UTF-8?q?=EB=AF=B8=EA=B5=AC=ED=98=84=20=EC=B7=A8=EC=95=BD=EC=A0=90=20?= =?UTF-8?q?=EC=83=81=EC=84=B8=20=EB=AC=B8=EC=84=9C=ED=99=94?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 본인 확인 검증 문제 정확한 플로우 추가 - JWT 토큰 구성 (Gmail/Slack) 상세 명시 - 취약 엔드포인트 목록 업데이트 - JWT.sub ≠ URL.user_id 검증 없음 명확화 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude --- ...d_backend_preferences_API_연동_완료.md | 64 ++++++++++++++++++- 1 file changed, 61 insertions(+), 3 deletions(-) diff --git a/troubleshooting/250827_frontend_backend_preferences_API_연동_완료.md b/troubleshooting/250827_frontend_backend_preferences_API_연동_완료.md index 4b5cc75..737d5c3 100644 --- a/troubleshooting/250827_frontend_backend_preferences_API_연동_완료.md +++ b/troubleshooting/250827_frontend_backend_preferences_API_연동_완료.md @@ -105,9 +105,67 @@ const scheduledTasks: ScheduledTask[] = [...]; // 하드코딩 - localStorage 기반으로 다른 디바이스와 동기화 안됨 - WebSocket이나 polling 구현 없음 -### 3.7 권한 검증 누락 -- user_preferences 수정 시 본인 확인 로직 필요 -- 다른 사용자 설정 수정 가능한 보안 문제 +### 3.7 🔴 권한 검증 누락 (본인 확인 미구현) + +#### 확인된 사실 (2025-09-15) + +**전체 플로우:** +1. **Frontend** (`/home/admin/frontend-customer/src/components/activity-panel.tsx`) + - Line 85: `GET ${API_BASE}/api/preferences/${userId}` + - Line 155: `PUT ${API_BASE}/api/preferences/${userId}` + - userId는 localStorage에서 읽음 (Line 76) + - Authorization 헤더에 Bearer 토큰 포함 (Line 87, 158) + +2. **Gateway** (`/home/admin/robeing-gateway/app/main.py`) - 51123:8100 + - Line 365-391: `/api/preferences/{path}` 엔드포인트 + - Line 369: `user_uuid = Depends(get_verified_user)` - JWT에서 UUID 추출 + - Line 375-376 (GET): `http://192.168.219.52:9024/api/preferences/{path}` 프록시, 헤더 없음 + - Line 377-382 (PUT): + - robeing-monitor로 프록시 + - `X-User-Id: user_uuid` 헤더 추가 (Line 382) + - **문제점**: URL의 {path}와 JWT의 user_uuid 비교 없음 + +3. **robeing-monitor** (`/home/admin/ivada_project/robeing-monitor/app/api/monitor.py`) - 51124:9024 + - Line 129: `async def get_preferences(user_id: str):` + - Line 194: `async def update_preferences(user_id: str, preferences: UserPreferencesUpdate):` + - 파라미터: URL의 {user_id}만 사용, Request 객체 없음 + - **문제점**: JWT/헤더 검증 불가능 + +#### 취약점 핵심: JWT.sub ≠ URL.user_id 검증 없음 + +**문제**: URL의 user_id를 아무나 바꿔서 타인 데이터를 조회/수정 가능 +- JWT의 sub(본인 UUID)과 URL의 user_id(대상 UUID)가 같은지 확인 안 함 + +```bash +# 정상 요청 (자기 데이터) +PUT /api/preferences/1e16e9d5-59f3-54da-a661-8abeabff4230 +Authorization: Bearer [JWT with sub=1e16e9d5-59f3-54da-a661-8abeabff4230] + +# 취약 요청 (타인 데이터 수정 가능) +PUT /api/preferences/b6ea2ee0-a15a-5cf4-93a9-a9ca20d4c4a0 +Authorization: Bearer [JWT with sub=1e16e9d5-59f3-54da-a661-8abeabff4230] +# Gateway는 X-User-Id: 1e16e9d5를 전달하지만 +# robeing-monitor는 URL의 b6ea2ee0를 사용 +``` + + +#### 관련 서비스 JWT 검증 현황 (2025-09-15 확인) + +**JWT 토큰 발급:** +- auth-server: JWT sub에 user.id(UUID) 사용 (`/home/admin/auth-server/app/providers/gmail.py` L198~, `slack.py` L329) +- 알고리즘: HS256, 만료: 30일 (`/home/admin/auth-server/app/core/auth.py`) +- Gmail OAuth JWT: `sub`(user UUID), `username`, `email`, `name`, `exp`(만료시간), `iat`(발급시간) +- Slack OAuth JWT: `sub`(user UUID), `email`, `name`, `username`, `picture`(프로필 이미지), `slack_user_id`, `slack_team_id`, `exp`, `iat` + +**JWT 검증 구현된 서비스:** +- Gateway: 모든 주요 엔드포인트에서 `Depends(get_verified_user)` 사용 +- rb8001: `/api/message`에서 JWT 검증, sub(UUID)를 user_id로 사용 + +**JWT.sub 매칭 없는 취약 엔드포인트:** +- Gateway: `/api/workspace/{user_id}`, `/api/workspace/assign` - Depends(get_verified_user) 없음 +- robeing-monitor: Preferences API (`/api/preferences/{user_id}`) - 경로 user_id만 사용 +- robeing-monitor: Gmail Items API - X-User-Id와 경로 user_id 일치만 확인, JWT.sub 매칭 없음 +- rb10508_micro: `/memories/{user_id}`, `/user/{user_id}/history` - JWT 검증 없음 ---