FlawOpen

flawopen.com/Teardowns/cve-2026-27826-mcp-atlassian-ssrf

● CVE-2026-27826 · CVSS 8.2[1], [3] · 높음
보안 연구 · FlawOpen

CVE-2026-27826: MCP Atlassian 헤더 SSRF

CVE-2026-27826의 최초 헤더 기반 SSRF는 0.17.0에서 수정됐습니다. 이후 확인된 별도 SSRF 결함은 0.22.0에서 수정됐으므로 전체 환경의 최소 버전을 정하기 전에 각 권고를 확인하세요.[1], [2], [6], [8], [9], [10], [11]

💡 알기 쉬운 설명 (ELI5)

회사 우편실이 승인된 사무실로만 소포를 보낼 수 있다고 생각해 보세요. 방문자가 특별 양식에 다른 주소를 적었는데 직원이 확인하지 않고 그대로 따릅니다. 서버 fetcher가 바로 그 우편실입니다. 요청 헤더가 목적지를 정했고 서버가 외부 요청을 보냈습니다. 0.17.0 수정은 연결 전에 제출된 URL을 확인하고 리디렉션 대상도 검사합니다. 운영자는 허용 도메인 목록을 추가로 설정할 수 있습니다.[1], [2]

핵심 개념 및 용어

Server-side request forgery (SSRF)
호출자가 서버의 아웃바운드 요청을 조작해 애플리케이션이 연락하려 하지 않았던 대상으로 보내는 취약점입니다.[1], [4]
MCP 전송 방식
MCP 클라이언트와 서버 사이의 통신 채널입니다. 이 문제는 streamable-HTTP와 SSE 전송에 영향을 줬으며, 권고문에서 설명한 stdio 전용 배포에는 해당 HTTP 헤더 경로가 없습니다.[1]
헤더 기반 멀티테넌트 인증
요청마다 Atlassian URL과 토큰을 받아 특정 테넌트용 API 클라이언트를 만드는 방식입니다.[1], [2]
아웃바운드 네트워크 정책
서비스가 접속할 수 있는 대상을 제한해 애플리케이션 URL 검증의 빈틈이 미치는 영향을 줄이는 네트워크 제어입니다.[12], [1]
간접 프롬프트 인젝션
도구가 반환하는 신뢰할 수 없는 콘텐츠에 모델에 영향을 줄 지시가 포함될 수 있습니다. 이 CVE 권고문은 공격자가 통제하는 응답이 도구 결과에 들어가는 경로를 설명하며, 이는 SSRF 자체와는 별도의 영향입니다.[1], [7]
후속 SSRF 수정 사항
CVE-2026-27826 최초 권고는 0.17.0을 수정 버전으로 안내합니다. 이후 유지관리자는 불완전한 수정 경로 네 건을 CVE-2026-77242, CVE-2026-77267, CVE-2026-77249, CVE-2026-77274로 별도 공개했으며, 각 권고는 0.22.0을 수정 버전으로 표시합니다. 이는 별도의 CVE이며 CVE-2026-27826의 영향 버전 범위를 넓히는 것이 아닙니다. 전체 환경의 최소 버전을 결정하기 전에 후속 권고도 확인하세요.[8], [9], [10], [11]

프레임워크 매핑

근본 원인 분석 (Root Cause)

영향받는 HTTP 경로에서 서버는 요청의 X-Atlassian-Jira-Url 또는 X-Atlassian-Confluence-Url을 읽어 fetcher 생성에 사용하는 JiraConfig 또는 ConfluenceConfig에 전달했습니다. 취약한 헤더 기반 인증 분기에서는 fetcher가 첫 요청을 보내기 전에 목적지를 서버에 설정된 테넌트 URL이나 목적지 정책과 대조하지 않았습니다. 유지관리자 권고문은 개별 MCP 도구 핸들러가 아니라 요청 middleware와 dependency provider 경로를 근본 원인으로 지목합니다. 이 문제에는 영향받는 HTTP 전송 방식과 헤더 인증 조건이 필요하므로 모든 MCP 배포에 일반화하면 안 됩니다.[1], [2]

단계별 공격 실행 흐름

단계 1

접근 가능한 HTTP 전송

배포가 streamable-HTTP 또는 SSE를 사용하고 MCP 엔드포인트를 접근 가능한 호출자에게 노출합니다.[1], [2]

단계 2

요청 헤더가 서비스 URL 선택

영향받는 헤더 인증 경로에서 Jira 또는 Confluence URL 및 토큰 헤더가 있고 대체 경로가 기대하는 Authorization 헤더는 없습니다.[1], [2]

단계 3

Middleware가 fetcher 생성

Middleware가 받은 URL을 저장하고 dependency provider는 의도된 목적지 경계를 적용하지 않은 채 Atlassian fetcher 설정에 사용합니다.[1], [2]

단계 4

서버가 아웃바운드 요청 전송

Fetcher 초기화가 호출자 지정 목적지로 요청을 보냅니다. 네트워크 접근성과 응답에 따라 내부 서비스가 노출되거나 공격자 통제 콘텐츠가 도구 결과에 들어갈 수 있습니다.[1], [2]

소스 코드 비교: 취약한 구현 vs 보안 패치

취약한 발췌 코드는 요청 헤더의 URL이 서버의 아웃바운드 목적지를 선택하게 합니다. 업스트림 0.17.0 패치는 이 헤더 기반 테넌트 방식을 서버 측 테넌트 레지스트리로 대체하지 않습니다. fetcher를 만들기 전에 ASGI 미들웨어에서 전달된 Jira 또는 Confluence URL을 검증하고, 이후 response hook을 추가해 리디렉션 목적지도 검사합니다. 강화된 발췌는 이 두 업스트림 제어를 보여 주며 validator 구현은 생략했습니다. 서버 측 테넌트 레지스트리는 더 강한 대안 아키텍처이지 이 패치가 구현한 내용은 아닙니다. 0.22.0 후속 권고에는 별도의 잔여 경로가 기록되어 있으므로 이를 검토하지 않고 0.17.0을 전체 fleet의 최소 버전으로 간주하지 마세요. DNS rebinding 방어를 위해 연결 시점에도 DNS 검증을 적용해야 합니다. 호스트명을 한 번만 조회하는 것으로 SSRF 경계가 완전히 닫히지는 않습니다.[1], [2]

소스 코드 발췌: 업스트림 미들웨어 및 fetcher 패치 발췌(Jira 경로이며 Confluence에도 같은 검사가 있습니다).

취약한 구현
header_jira_fetcher = JiraFetcher(config=header_config)
current_user_id = header_jira_fetcher.get_current_user_account_id()
보안 강화 패치
ssrf_error = validate_url_for_ssrf(jira_url_str)
if ssrf_error:
    scope["state"]["auth_validation_error"] = (
        f"Forbidden: Invalid Jira URL - {ssrf_error}"
    )
    return

header_jira_fetcher = JiraFetcher(config=header_config)
header_jira_fetcher.jira._session.hooks["response"].append(
    _make_ssrf_safe_hook(validate_url_for_ssrf)
)
current_user_id = header_jira_fetcher.get_current_user_account_id()

엔지니어링 및 시스템 보안 강화 체크리스트

출처